Mixing async/await with Result - c#

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.)

Related

How to display a message while program is running?

I am working on a user interface in C#.
When the program is running (this process takes several minutes...), before run, I want a message is displayed and after run, the message will disappear automatically.
My aim is to give an information message like 'Running, please wait' to the user.
I tried the code shown below:
(formMsgWait has only a label 'Running, please wait')
private void btnExit_Click(object sender, EventArgs e)
{
using (formMsgWait fMsgWait = new formMsgExit())
{
fMsgWait.Show();
System.Windows.Forms.Application.DoEvents();
...statement 1
...statement 2
...
}
}
When run to System.Windows.Forms.Application.DoEvents(); the program doesn't run continue, so all of the statements below doesn't do (...statement 1, ...statement 2, ...), formMsgWait doesn't close.
Is there anyway to do that?
Any tips on these will be great help.
You're blocking the current thread. According to http://msdn.microsoft.com/en-us/library/system.windows.forms.application.doevents.aspx
Calling this method causes the current thread to be suspended while
all waiting window messages are processed. If a message causes an
event to be triggered, then other areas of your application code may
execute. This can cause your application to exhibit unexpected
behaviors that are difficult to debug. If you perform operations or
computations that take a long time, it is often preferable to perform
those operations on a new thread. For more information about
asynchronous programming, see Asynchronous Programming Overview.
So that's what you should actually be doing here: start all of your actual work on a separate thread, preferably using async. For example:
public async Task<bool> DoTheWorkAsync()
{
formMsgWait f = new formMsgWait();
f.Show();
bool finished = await Task.Run(() => DoTheWork());
f.Close();
return finished;
}
private bool DoTheWork()
{
... work
return true;
}
Oh. I think you can use Dialog Window. Visit this link to refer:
https://msdn.microsoft.com/en-us/library/c7ykbedk(v=vs.110).aspx

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();

C# wait until its completed

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!)

Issue using Task.Factory.FromAsync

I enjoyed the new C# 5's async and await and I want to set it up to one of my previous Tcp application which I used the async whay (not async & await, in fact Begin*, End*)
in my application every message have a response, so every time you use BeginSend, you will receive a message related the message you first sent. (lets suppose command and it's report)
I want to add a new function called RequestAsync that you send your message and wait till the response comes. let me show the usage
string response = await RequestAsync("hi");
on this occasion, you will send a "hi" message and then code waits till the response related to this comes.
I had problems using Task.Factory.FromAsync, so I tried the following code, i want to make sure the performance is roughly the same as TaskFactory way.
public async Task<IRequestResult> SendRequestAsync(IRequest request, string message)
{
IRequestResult result = BeginSendRequest(request, message);
while (!result.IsCompleted)
{
await Task.Delay(1);
}
return result;
}
and BeginRequest is my own method.
Sincerely yours,
Peyman Mortazavi
No, that's going to be pretty awful in terms of efficiency - you'll be waking up and requiring rescheduling every 5 milliseconds. You've added latency while you effectively sleep between cycles as well.
You should go back to trying to use Task.Factory.FromAsync - you haven't told us what went wrong when you tried that, so it's hard to help you fix it... It's possible that you haven't implemented the asynchronous programming model pattern correctly to start with. (The fact that you're not providing a callback to your BeginSendRequest method is suggestive of that.)
I hope your real code doesn't have catch {} either...
Poling can never be efficient as IO completion ports, and why even use an async method if you are only waiting for it and not doing anything in the mean time, it just ads needles overhead.

Threading in Form_Load - Application now hangs suddenly

Sorry for the lengthy post, I just want to illustrate my situation as best as possible. Read the items in bold and check the code if you want the quick gist of the issue.
I use ClickOnce to deploy a C# application, and have opted to have my application check for updates manually using the ApplicationDeployment Class rather than letting it do the update checking for me.
The program is a specialized network scanner that searches for network devices made by the company I work for. Once the main window is loaded, a prompt is displayed asking if the user would like to scan the network. If they say Yes, a scan begins which can take a minute or two to complete depending on their network settings; otherwise it just waits for the user to do some action.
One of the last things I do in Form_Load is create a new thread that checks for updates. This had all been working fine for several months through about 12 releases and has suddenly stopped working. I didn't change the update code at all, nor change the sequence of what happens when the app starts.
In staring at the code, I think I see why it is not working correctly and wanted to confirm if what I think is correct. If it is, it begs the question as to why it DID work before - but I'm not too concerned with that either.
Consider the following code:
frmMain.cs
private void Form1_Load(object sender, EventArgs e)
{
// set up ui, load settings etc
Thread t = new Thread(new ParameterizedThreadStart(StartUpdateThread));
t.Start(this);
}
private void StartUpdateThread(object param)
{
IWin32Window owner = param as IWin32Window;
frmAppUpdater.CheckForUpdate(owner);
}
frmAppUpdater.cs
public static void CheckForUpdate(IWin32Window owner)
{
if (ApplicationDeployment.IsNetworkDeployed) {
Console.WriteLine("Going to check for application updates.");
parentWindow = owner;
ApplicationDeployment ad = ApplicationDeployment.CurrentDeployment;
ad.CheckForUpdateCompleted += new CheckForUpdateCompletedEventHandler(ad_CheckForUpdateCompleted);
ad.CheckForUpdateProgressChanged += new DeploymentProgressChangedEventHandler(ad_CheckForUpdateProgressChanged);
ad.CheckForUpdateAsync();
// CAN/WILL THE THREAD CREATED IN FORM1_LOAD BE TERMINATED HERE???
}
}
When the CheckForUpdateAsync() callback completes, if no update is available the method call simply returns; if an update IS available, I use a loop to block until 2 things occur: The user has dismissed the "Would you like to scan prompt" AND no scan is currently running.
The loop looks like this, which takes place in ad_CheckForUpdateCompleted:
while (AppGlobals.ScanInProgress || AppGlobals.ScanPromptVisible) {
System.Threading.Thread.Sleep(5000);
}
I sleep for 5 seconds because I figured this was happening in a separate thread and it has seemed to work well for a while.
My main question about the above code is:
When ad.CheckForUpdateAsync(); is called from CheckForUpdate does the thread I created in Form1_Load terminate (or might it terminate)? I suspect it may because the subsequent Async call causes the method to return, and then start another thread?
The only reason I am confused is because this method WAS working for so long without hanging the application and now all of the sudden it hangs and my best effort at debugging revealed that it was that Sleep call blocking the app.
I'd be happy to post the full code for frmAppUpdater.cs if it would be helpful.
When ad.CheckForUpdateAsync(); is called from CheckForUpdate does
the thread I created in Form1_Load terminate (or might it terminate)?
If the CheckForUpdateAsync() call is asynchronous then yes, the thread will terminate, no it won't otherwise.
If you suspect the Sleep to have caused the application hang then these two variables AppGlobals.ScanInProgress and AppGlobals.ScanPromptVisible are probably always set to true! You should start looking at the code that is setting them to true and see what is going on there.
In order to avoid an application hang, you could introduce a variable to avoid sleeping indefinitely:
int nTrials = 0;
while ((AppGlobals.ScanInProgress || AppGlobals.ScanPromptVisible) && (nTrials < 5)) {
System.Threading.Thread.Sleep(5000);
nTrials++;
}
// Check the results and act accordingly
I personally do not like using Sleep for thread synchronization. .NET offers a bunch of classes that are perfect for thread synchronization, WaitHandle being one of them.
See this post at Asynchronous Delegates Vs Thread/ThreadPool?
your form load method seems to be doing synchronous work. you mention that you are using clickonce deployment. Has the binary location changed after the previous release or has permissions on this resource changed. Looks like the work (checkupdates) in the Thread is never finishing and is never handed back to the form.
as an immediate fix, I would change the Thread approach to Delegate - if you use delegate, then this becomes less of a customer issue (the form will respond to end user) but the underlying problem remains.
as the next step, i would go through http://msdn.microsoft.com/en-us/library/ms229001.aspx and do the troubleshoot

Categories

Resources