views:

245

answers:

2

Hi, I'm programming simple TCP file transfer using TcpListener on reciever side and TcpClient on sender side. I have 2 options - synchronnous or asynchronnous. If I use synchronnous, I have to put sending/recieving methods into BackgroundWorker, to prevent freezing GUI thread. Asynchronnous version is without problems...

My question is, how to stop running file transfer?

In synchronnous version I tried to use BackgroundWorker.CancelAsync() method, and in every loop iteration check BackgroundWorker.CancellationPending property, but it doesn't seems to work (CancelAsync is probably not setting CancellationPending property) :(

In asynchronnous version I tried to use volatile variable Indicator and in every Callback check its value. Problem is, when I change its value in Stop() method, and than I check it in Callback, callback still reads its previous value :(

A: 

CancelASync should work; did you set:

backgroundWorker.WorkerSupportsCancellation = true:
Mark B
Of course. If I didn't it will throw an exception, wouldn't it?
Klinki
Oh now i know why it is not cancelling at all :) I had BackgroundWorker.CancelAsync() in FormClosing event and it doesn't set CancellationPending property because Form was already closed :) Now I added e.Cancel into FormClosing event and its working :)
Klinki
A: 

Are you saying that you aren't reading the correct "cancel state" when you check it? This suggests you're not synchronising the flag between your threads correctly.

Or is it just that you won't ever check for the "cancel state" unless you receive some new data? (From the way you describe your tx/rx "loops", in both sync and async cases you will have to receive a new datagram before you will get a chance to check the 'cancel' flag)

If you are in control of both ends of the data transfer, then whichever end (client or server) wishes to abort should ideally send a special datagram to the other end to stop the transfer - otherwise the other end will attempt to continue sending/receiving, not knowing that it's on its own. So perhaps a better approach would be to actually send/receive a "cancel transfer" datagram, which would inform the TCP code at both ends that you wish to cancel. (i.e. you wouldn't need to have a special cancel flag, you would simply check if the datagram you are about to send or have just received is a "cancel transfer" datagram). This would allow both ends to gracefully and cleanly close down.

Jason Williams
This is actually really good idea :) I though I will catch exceptions, when client closed connection, but this is much better solution. And its simple, just add asynchronnous read into NetworkStream on senders side... And when it reads something it means client sended stop message :) Thank you!
Klinki
You will still need to catch exceptions (comms may simply fail - a good idea is to test your final code by unplugging the network cable in mid transfer), but it is nice to allow the endpoints to negotiate a conclusion rather than just pulling the plug on each other.
Jason Williams