C# wait until its completed - c#

I have some code, and I have noticed it makes my app freeze. I'm looking for a solution that is better than mine.
How to wait for values which I don't know when I receive and I can't continue until I get them and only solution I figured up was using while until I receive those values.
I'm looking for better solution. The best if it wouldn't freeze my app. It has been told me I should use events, but I couldn't figure out how to do that.
IsBusy = true;
do
{
if (IsBusy)
{
//waiting for values which i don't know when i receive
//i can receive those values in 1sec and also in 2 min
if done -> IsBusy = false;
}
Thread.Sleep(2000);
} while (IsBusy);
IsBusy = true;
do
{
if (IsBusy)
{
//waiting for similar thing until i receive it
if done -> IsBusy = false;
}
Thread.Sleep(5000);
} while (IsBusy);

I think best way to use async await. In C#, asynchronous programming with async await is very easy. Code looks like synchronous.
private async void StartButtonClick(object sender, RoutedEventArgs e)
{
// Starting new task, function stops
// the rest of the function is set to cont
// UI not blocked
Task.Run(async () =>
{
var MyValue = await doSomethingAsync();
}); //there you waiting value
//continue code
}

There may be a couple possibilities, though the description of what you're waiting on is vague enough we may not be able to point you in a specific direction. Some things that might work are:
Event-based coding. If you can change the code of the process you're waiting for, you can have it raise an event that your calling code then handles. This other SO answer has a simple, complete C# program that raises and handles events.
BackgroundWorker often works well in Windows Forms projects, in my experience. In my experience it's one of the simpler ways to get started with multithreading. There's a highly-rated tutorial with code samples here that may help.
There are other ways to multithread your code, too (so that it doesn't "freeze up" while you're waiting), but these may be a simpler starting point for doing what you need.
Async/await may work for you, but I find they're most useful when you already have an existing doSomethingAsync()-type method to work with (such as async web/WCF service methods in a .NET-generated proxy). But if all the code's your own and you're trying to multithread from scratch, they won't be the central mechanism you'd use to get started. (Of course, if it turns out you are waiting on something with a built-in ...Async() method like a web service call, by all means use async/await, and please select #Astemir-Almov's as the accepted answer!)

Related

Cancel/Abort a Task in C#

I have a program in C# which does some services calls.
I need to add some code in this program in order to be able to stop these services calls if I click on a button (winform) [For example, if the call is too long and the user is bored].
The difficulty is that I can't modify the blocks of code which do the calls.
In order to do so, I've planned to do some Interception with the Unity Framework.
I would like to create a Task each time I enter a service-call block of code. Then, cancel this task if the user clicks on my Button.
I've looked about CancellationToken but the problem is that I can't modify the calls-blocks, so I can't do if(ct.IsCancellationRequested) or ct.ThrowIfCancellationRequested();
Same thing for the AutoResetEvent & ManualResetEvent.
The calls are not always asynchronous and made with a cancellationToken, so catching OperationCanceledExceptionis, I think, impossible.
I've also looked about using Threads and do some Thread.Abort() but this method seems to kill puppies each time someone calls it.
Here is a sample of my current program (the Interception is not implemented yet, I want to test it on a single call first) :
private void Test()
{
Task.Factory.StartNew(MyServiceCallFunction); // How to cancel the task when I press a button ?
}
// Can't touch the inside of this function :
private void MyServiceCallFunction()
{
// Blabla I prepare the datas for the call
// Blabla I do the call
}
How can I do that ? (I'm not obliged to use a task)
Thank you,
The "correct" way to do it is to used CancellationTokens but since you can't modify the running code the only other way is to kill the puppies and use Thread.Abort()
Something like:
Thread t;
Task.Factory.StartNew(() =>
{
t = Thread.CurrentThread;
MyServiceCallFunction();
});
t.Abort();
Very Interesting question. Of course you cannot do anything when the third party call is doing TPL; in your case it is MyServiceCallFunction().
I have been in the similar situation where this blog post has helped me: https://social.msdn.microsoft.com/Forums/vstudio/en-US/d0bcb415-fb1e-42e4-90f8-c43a088537fb/aborting-a-long-running-task-in-tpl?forum=parallelextensions
(read: Stephen Toub - MSFTMicrosoft (MSFT) comments)
He has mentioned this solution:
int Test(CancellationToken token)
{
Thread currentThread = Thread.CurrentThread;
using (token.Register(currentThread.Abort))
{
MyServiceCallFunction()
}
}
Also replace Task.Factory.StartNew (...) with Task.Run(...) ; same, infect latter is stronger, but better readable.

Mixing async/await with Result

Let me just preface this question with a few things:
I've read several SO questions saying that you should not do this (such as How to safely mix sync and async code)
I've read Async/Await - Best Practices in Asynchronous Programming again saying you shouldn't do this
So I do know that this is not a best practice, and don't need anyone telling me such. This is more of a "why does this work" question.
With that out of the way, here is my question:
I've written a small GUI application that has 2 buttons and a status label. One of the buttons will reproduce the deadlock issue with sync and async 100% of the time. The other button calls the same async method but it is wrapped in a Task, this one works. I know this is not a good coding practice, but I want to understand why it doesn't have the same deadlock issue. Here is the code:
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private async Task<string> DelayAsync()
{
await Task.Delay(1000);
return "Done";
}
private void buttonDeadlock_Click(object sender, EventArgs e)
{
labelStatus.Text = "Status: Running";
// causes a deadlock because of mixing sync and async code
var result = DelayAsync().Result;
// never gets here
labelStatus.Text = "Status: " + result;
}
private void buttonWorking_Click(object sender, EventArgs e)
{
labelStatus.Text = "Status: Running";
string result = null;
// still technically mixes sync and async, but works, why?
result = Task.Run(async () =>
{
return await DelayAsync();
}).Result;
labelStatus.Text = "Status: " + result;
}
}
It works because the buttonWorking_Click async code (DelayAsync as well as the async lambda passed to Task.Run) does not have a current SynchronizationContext, whereas the buttonDeadlock_Click async code (DelayAsync) does. You can observe the difference by running in the debugger and watching SynchronizationContext.Current.
I explain the details behind the deadlock scenario in my blog post Don't Block on Async Code.
Scenario one: you are sitting at your desk. There is an inbox. It is empty. A piece of paper suddenly arrives in your inbox describing a task. You jump to your feet and start running around doing the task. But what is the task? It says to do the following:
Change the whiteboard to say "running" -- OK, you do that.
Set your alarm clock for an hour later. OK, you do that.
Create a new piece of paper that says "when the alarm goes off, write the word DONE on the whiteboard". Put it in your inbox. You do that.
Do nothing else until the word DONE is written on the whiteboard.
Go back to your desk and wait for the next task to arrive in the inbox.
This workflow prevents you from getting work done because the last two steps are in the wrong order.
Scenario two: you are sitting at your desk. There is an inbox. It is empty. A piece of paper suddenly arrives in your inbox describing a task. You jump to your feet and start running around doing the task. But what is the task? It says to do the following:
Change the whiteboard to say "running" -- OK, you do that.
Give this other piece of paper to Debbie in the next cubicle. OK, you do that.
Do nothing until someone tells you that the sub-task is DONE.
When that happens, write the word DONE on your whiteboard.
Go back to your desk.
What does the piece of paper you gave Debbie say? It says:
Set your alarm clock for an hour later. OK, she does that.
When the alarm goes off, put a piece of paper in your inbox saying to tell Middas that you're done.
This workflow still is terrible in that (1) you are sitting there doing nothing while you wait for Debbie's alarm clock to go off, and (2) you are wasting the time of two workers when you could have a single worker do all the work. Workers are expensive.
But this workflow does not prevent you from getting work done eventually. It doesn't deadlock because you are not waiting on work that you yourself are going to do in the future, you are waiting for someone else to do the work.
(I note that this is not an exact analogy for what is happening in your program, but it is close enough to get the idea across.)

Use async/ await or something else

I'm writing a program that communicates with some control hardware that I've designed. The hardware is driving motors and the first thing I'm trying to do with it is to initialize a motor.
The hardware is comm controlled, so to do anything I simply send a message out through USB to the hardware.
To initialize a motor I have to send 2 messages; after I send the first one it moves the motor toward a sensor, and when it reaaches it it stops and sends a message back to me telling me that it has stopped, at which point I send it another message telling it to drive the motor in the opposite direction very slowly until it comes out of the sensor.
All of my comms reception is in a SerialPort DataReceived event. What is the best way that I can wait for the relevant message and then send the second message? At the moment I'm simply using a property of type bool which I set to true just before initialization, and then in my event handler if I receive the message telling me that the motor has stopped and the bool is true, I set the bool to false and send the second message. While this works I was thinking that it might be possible to use async and await? And that this might be a little more efficient in general? Or is there another approach that I could take that would be better?
Any feedback/ guidance will be greatly appreciated!
In my opinion, the nice thing about async-await is not that it keeps your caller responsive, but your code looks easier, almost as if it was not async-await.
Keeping your caller responsive can also be accomplished using Tasks and ContinueWith statements, or by using a Backgroundworker or other methods to create a thread. But if you use async await, you don't have to remember the state of your progress, something you do now by setting the boolean.
Your code would look like this:
public Task InitializeAsync(...)
{
await Send1stMessageAsync();
await Send2ndMessageAsync();
}
In this article Eric Lippert explained async-await using a kitchen metaphor. What happens is that your thread will do everything to send the 1st message until it can't do anything anymore but wait for the reply. Control is then given to the first caller who is not awaiting. That would have been you if you weren't awaiting, for instance if you had the following code:
public Task InitializeAsync(...)
{
var task1stMessage = Send1stMessageAsync();
// this thread will do everything inside Send1stMessageAsync until it sees an await.
// it then returns control to this function until there is an await here:
DoSomeThingElse();
// after a while you don't have anything else to do,
// so you wait until your first messages has been sent
// and the reply received:
await task1stMessage;
// control is given back to your caller who might have something
// useful to do until he awaits and control is given to his caller etc.
// when the await inside Send1stMessageAync is completed, the next statements inside
// Send1stMessageAsync are executed until the next await, or until the function completes.
var task2ndMessage = Send2ndMessageAsync();
DoSomethingUseful();
await task2ndMessage;
}
You wrote that you use events to notify your thread that the data has been received. Although it is not difficult to make your Send1stMessageAsync an async function, you don't have to reinvent the wheel. Consider using a nuget package like SerialPortStream to get async functions that send messages and wait for reply.
I you are waiting for something to happed and you don't have event handler at your disposal it would be a good idea to use async/await pattern
async Task WaitForCompletion()
{
await Task.Run(()=>
{
while(!theBoolVar)
Thread.Sleep(1000);
});
}
and then just in your code use
await WaitForCompletion();

How to terminate a thread when the worker can't check the termination string

I have the following code running in a Windows form. The method it is calling takes about 40 seconds to complete, and I need to allow the user the ability to click an 'Abort' button to stop the thread running.
Normally I would have the Worker() method polling to see if the _terminationMessage was set to "Stop" but I can't do this here because the long running method, ThisMethodMightReturnSomethingAndICantChangeIt() is out of my control.
How do I implement this user feature please ?
Here is my thread code.
private const string TerminationValue = "Stop";
private volatile string _terminationMessage;
private bool RunThread()
{
try
{
var worker = new Thread(Worker);
_terminationMessage = "carry on";
_successful = false;
worker.Start();
worker.Join();
finally
{
return _successful;
}
}
private void Worker()
{
ThisMethodMightReturnSomethingAndICantChangeIt();
_successful = true;
}
Well, the simple answer would be "you can't". There's no real thread abort that you can use to cancel any processing that's happenning.
Thread.Abort will allow you to abort a managed thread, running managed code at the moment, but it's really just a bad idea. It's very easy to end up in an inconsistent state just because you were just now running a singleton constructor or something. In the end, there's quite a big chance you're going to blow something up.
A bit orthogonal to the question, but why are you still using threading code like this? Writing multi-threaded code is really hard, so you want to use as many high-level features as you can. The complexity can easily be seen already in your small snippet of code - you're Joining the newly created thread, which means that you're basically gaining no benefit whatsoever from starting the Worker method on a new thread - you start it, and then you just wait. It's just like calling Worker outright, except you'll save an unnecessary thread.
try will not catch exceptions that pop up in a separate thread. So any exception that gets thrown inside of Worker will simply kill your whole process. Not good.
The only way to implement reliable cancellation is through cooperative aborts. .NET has great constructs for this since 4.0, CancellationToken. It's easy to use, it's thread-safe (unlike your solution), and it can be propagated through all the method chain so that you can implement cancellation at depth. Sadly, if you simply can't modify the ThisMethodMightReturnSomethingAndICantChangeIt method, you're out of luck.
The only "supported" "cancellation" pattern that just works is Process.Kill. You'd have to launch the processing method in a wholy separate process, not just a separate thread. That can be killed, and it will not hurt your own process. Of course, it means you have to separate that call into a new process - that's usually quite tricky, and it's not a very good design (though it seems like you have little choice).
So if the method doesn't support some form of cancellation, just treat it like so. It can't be aborted, period. Any way that does abort it is a dirty hack.
Well, here's my solution so far. I will definitely read up on newer .NET higher level features as you suggest. Thanks for the pointers in the right direction
private void RunThread()
{
try
{
var worker = new Thread(Worker);
SetFormEnabledStatus(false);
_usuccessful = false;
worker.Start();
// give up if no response before timeout
worker.Join(60000); // TODO - Add timeout to config
worker.Abort();
}
finally
{
SetFormEnabledStatus(true);
}
}
private void Worker()
{
try
{
_successful= false;
ThisMethodMightReturnSomethingAndICantChangeIt();
_successful = true;
}
catch (ThreadAbortException ex)
{
// nlog.....
}
catch (Exception ex)
{
// nlog...
}
}

WPF threading help needed

Hopefully you can help.
Scenario
WPF Application calling a wcf Service to buy products etc...
A customer can select 20 products in the UI and press buy,now for each product that is processed I need to report a status EG("OK","Out of stock","Busy" etc...)
I have a txtReportProgress that is bind to a BuyCommand.
Problem
Even though everything seems to work ok and I receive a notification for each product processed it gets all out sync and not actually reporting the steps in the correct order.
I think this is todo with the fact that I have NOT implemented threading but I dont know how to do it.
I have read i can use "Dispatcher" i/o background worker but cannot make it work.
Noddy example here to give you an idea.
Can you help me and give me some pointers?
---CustomerViewModel
public ICommand BuyCommand
{
get
{
if (BuyCommand == null)
{
BuyCommand = new RelayCommand(param => Buy(), param => CanBuy);
}
return BuyCommand;
}
}
private void Buy()
{
ReportProgress("Buying Progress is starting");
ProductStatus status=myService.IsProductAvailable();
myService.ProcessProducts(); //For each product that is processed service does a callback and NotificationReceivedfromService is fired.THIS WORKS!!
ReportProgress(status);
var result =DoSomethingElse();
ReportProgress(result);
}
void NotificationReceivedFromService(object sender, StatusEventArg e)
{
//update the UI
ReportProgress(e.Message);
}
static bool CanBuy
{
get
{
return true;
}
}
public string CustomerLog
{
get { return _customerModel.CustomerLog; }
set
{
_customerModel.CustomerLog = value;
base.OnPropertyChanged("CustomerLog");
}
}
internal void ReportProgress(string text)
{
CustomerLog += text + Environment.NewLine;
}
What is the WCF communication channel? Are you making multiple requests to a service in parallel? I can't really see from your code where there is any multi-threading going on at all but I'm assuming that NotificationReceivedFromService is some kind of callback?
Anyhow, if you were using something like Dispatcher.BeginInvoke, your invokes should be executed in the order they were made as long as they all have the same dispatcher priority.
If however you are making multiple parallel requests to the service, you can't really control the order in which they will complete. You'll need to make one request, then make the next when the first completes, etc. Or you can change your design so that it doesn't depend on the order of operations.
As you get callbacks out of sync, obviously some multithreading is going on, perhaps without your realizing it. You are aware that that calls to WCF services can be handled asynchronously by the service itself? Read here for more information. Please elaborate on your question or show us some more code if you need more help.
As to Dispatchers and BackgroundWorkers, these are very different beasts:
Dispatcher.Invoke is used to update the UI from a different thread than the UI thread.
Backgroundworkers encapsulate tasks that run on the background, but conveniently have events that are thrown on the UI thread, thereby making it unnecessary to use the Dispatcher.Invoke call.
You can read more about BackgroundWorkers here
As mentioned already, the CallBack is asynchronous so you will have an ordering problem. can you arrange the call to the service in some way that you can bring back some token or other identifier that will help you report the progress in the correct order? Something you can sort on perhaps?

Categories

Resources