How do async in window phone? - c#

In app.xaml.cs
private void Application_Closing(object sender, ClosingEventArgs e)
{
A.onEndApp();
}
In class A
async public static void onEndApp()
{
string temp=await doSomething();
//code here
}
I have a problem,when I close an app,and then onEndApp() method is run,
when doSomething() run complete and {//code here} is not run,but if I put A.onEndApp() in
another method it run normaly,for example Application_Launching() method,it will be run
{//code here}
I think when app is running it no problem,but when app is closing it run await complete and then stop,I want to run complete method when I close app in async.

After Application_Closing is executed (synchronously), the OS will terminate the process. There might be a short delay before it does so, and that might be enough for you to finish writing to isolated storage, or it might not in which case you'll end up having corrupted state
I'll just take a direct quote from "Beware the perils of async/await in application lifecycle event handlers (in fact in any event handlers)" on Andy Wigley's blog.
Calling async code from Application_Deactivated or Application_Closing
The guidance here is “don’t'”. If you write your apps carefully, you can be saving changes to persistent data as you go along, so you shouldn’t have anything to do in the application lifecycle events.
If you must, you can try doing something like this:
SomeAsyncMethod().AsTask().Wait()
If the operation completes within the timeout period AND it doesn’t deadlock due to needing
to pump the UI thread, it will work… but don’t count on it.

Try this:
private void Application_Closing(object sender, ClosingEventArgs e)
{
var task = A.onEndApp();
task.Wait();
}
async public static Task onEndApp()
{
string temp = await doSomething();
//code here
}
Otherwise, you're effectively just spinning off a thread that will never get a chance to run to completion, because the application is closing out from underneath it, and the thread will get terminated before it can run.

Related

Creating an async resource watcher in c# (service broker queue resource)

Partly as an exercise in exploring async, I though I'd try creating a ServiceBrokerWatcher class. The idea is much the same as a FileSystemWatcher - watch a resource and raise an event when something happens. I was hoping to do this with async rather than actually creating a thread, because the nature of the beast means that most of the time it is just waiting on a SQL waitfor (receive ...) statement. This seemed like an ideal use of async.
I have written code which "works", in that when I send a message through broker, the class notices it and fires off the appropriate event. I thought this was super neat.
But I suspect I have gotten something fundamentally wrong somewhere in my understanding of what is going on, because when I try to stop the watcher it doesn't behave as I expect.
First a brief overview of the components, and then the actual code:
I have a stored procedure which issues a waitfor (receive...) and returns a result set to the client when a message is received.
There is a Dictionary<string, EventHandler> which maps message type names (in the result set) to the appropriate event handler. For simplicity I only have the one message type in the example.
The watcher class has an async method which loops "forever" (until cancellation is requested), which contains the execution of the procedure and the raising of the events.
So, what's the problem? Well, I tried hosting my class in a simple winforms application, and when I hit a button to call the StopListening() method (see below), execution isn't cancelled right away as I thought it would be. The line listener?.Wait(10000) will in fact wait for 10 seconds (or however long I set the timeout). If I watch what happens with SQL profiler I can see that the attention event is being sent "straight away", but still the function does not exit.
I have added comments to the code starting with "!" where I suspect I have misunderstood something.
So, main question: Why isn't my ListenAsync method "honoring" my cancellation request?
Additionally, am I right in thinking that this program is (most of the time) consuming only one thread? Have I done anything dangerous?
Code follows, I tried to cut it down as much as I could:
// class members //////////////////////
private readonly SqlConnection sqlConnection;
private CancellationTokenSource cts;
private readonly CancellationToken ct;
private Task listener;
private readonly Dictionary<string, EventHandler> map;
public void StartListening()
{
if (listener == null)
{
cts = new CancellationTokenSource();
ct = cts.Token;
// !I suspect assigning the result of the method to a Task is wrong somehow...
listener = ListenAsync(ct);
}
}
public void StopListening()
{
try
{
cts.Cancel();
listener?.Wait(10000); // !waits the whole 10 seconds for some reason
} catch (Exception) {
// trap the exception sql will raise when execution is cancelled
} finally
{
listener = null;
}
}
private async Task ListenAsync(CancellationToken ct)
{
using (SqlCommand cmd = new SqlCommand("events.dequeue_target", sqlConnection))
using (CancellationTokenRegistration ctr = ct.Register(cmd.Cancel)) // !necessary?
{
cmd.CommandTimeout = 0;
while (!ct.IsCancellationRequested)
{
var events = new List<string>();
using (var rdr = await cmd.ExecuteReaderAsync(ct))
{
while (rdr.Read())
{
events.Add(rdr.GetString(rdr.GetOrdinal("message_type_name")));
}
}
foreach (var handler in events.Join(map, e => e, m => m.Key, (e, m) => m.Value))
{
if (handler != null && !ct.IsCancellationRequested)
{
handler(this, null);
}
}
}
}
}
You don't show how you've bound it to the WinForms app, but if you are using regular void button1click methods, you may be running into this issue.
So your code will run fine in a console app (it does when I try it) but deadlock when called via the UI thread.
I'd suggest changing your controller class to expose async start and stop methods, and call them via e.g.:
private async void btStart_Click(object sender, EventArgs e)
{
await controller.StartListeningAsync();
}
private async void btStop_Click(object sender, EventArgs e)
{
await controller.StopListeningAsync();
}
Peter had the right answer. I was confused for several minutes about what was deadlocking, but then I had my forehead slapping moment. It is the continuation of ListenAsync after the ExecuteReaderAsync is cancelled, because it's just a task, not a thread of its own. That was, after all, the whole point!
Then I wondered... OK, what if I tell the async part of ListenAsync() that it doesn't need the UI thread. I will call ExecuteReaderAsync(ct) with .ConfigureAwait(false)! Aha! Now the class methods don't have to be async anymore, because in StopListening() I can just listener.Wait(10000), the wait will continue the task internally on a different thread, and the consumer is none the wiser. Oh boy, so clever.
But no, I can't do that. Not in a webforms application at least. If I do that then the textbox is not updated. And the reason for that seems clear enough: the guts of ListenAsync invoke an event handler, and that event handler is a function which wants to update text in a textbox - which no doubt has to happen on the UI thread. So it doesn't deadlock, but it also can't update the UI. If I set a breakpoint in the handler which wants to update the UI the line of code is hit, but the UI can't be changed.
So in the end it seems the only solution in this case is indeed to "go async all the way down". Or in this case, up!
I was hoping that I didn't have to do that. The fact that the internals of my Watcher are using async methodologies rather than just spawning a thread is, in my mind, an "implementation detail" that the caller shouldn't have to care about. But a FileSystemWatcher has exactly the same issue (the need to control.Invoke if you want to update a GUI based on a watcher event), so that's not so bad. If I was a consumer that had to choose between using async or using Invoke, I'd choose async!

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

Execute async command before navigating back

I am using Modern UI for WPF template in a .NET 4.0 app where one page needs to execute an async command before it navigates back to another page. At the same time, UI thread must be unlocked while command is running. If I do this:
public void OnNavigatingFrom(FirstFloor.ModernUI.Windows.Navigation.NavigatingCancelEventArgs e)
{
TaskEx.Run(() =>
{
//Replace Sleep call by the async command execution
System.Threading.Thread.Sleep(5000);
}).Wait();}
The OnNavigatingFrom waits before navigating back, but the UI is blocked during this time.
Any ideas on how to execute the async code in a different context and make OnNavigatingFrom runs "synchronously"?
EDIT: There is a similar thread with a workaround and no conclusive answer.
one page needs to execute an async command before it navigates back to another page
This is the problem. User interfaces are not asynchronous, period. You can't just stick an asynchronous operation into the mix while the UI is doing a transition.
Think about it this way: as a user, if you decide to navigate back, and there's a network hiccup or something and the program freezes for a few seconds while navigating back, that's a bad user experience, right? The UI simply can't wait for asynchronous work during an update.
What you can do is do the work before the user is allowed to navigate back. You can, for example, capture the user's intent to navigate back and show some kind of "please wait" UI while the operation is going, and then after the operation completes do the actual navigation.
Here is what you need to do:
public void OnNavigatingFrom(NavigatingCancelEventArgs e)
{
// Fire and forget.
Task.Run(() => MyCommandAsync());
}
The above is a fire and forget approach, instead it is preferred to use async and await:
public async void OnNavigatingFrom(NavigatingCancelEventArgs e)
{
await MyCommandAsync();
}
Just await the Task instead of using .Wait().
See Using async-await on .net 4 for how to await in .NET 4.0
Use OnNavigatingFrom to do your stuff. e.Cancel prevent going back. Use Frame.GoBack() after your operation has finished.
protected override async void OnNavigatingFrom(NavigatingCancelEventArgs e)
{
if (Current.HasModifications())
{
e.Cancel = true;
await Current.Save().ContinueWith((t) =>
{
//Go Back after the Operation has finished
Frame.GoBack();
}, TaskScheduler.FromCurrentSynchronizationContext());
}
else
{
base.OnNavigatingFrom(e);
}
}

C#/.NET 4.5 - Why does "await Task.WhenAny" never return when provided with a Task.Delay in a WPF application's UI thread?

Given the following code, why does ask.WhenAny never return when provided with a Task.Delay of 1 second? Technically I'm not sure if it does return after a extended amount of time, but it doesn't after 15 seconds or so after which I manually kill the process. According to the documentation I shouldn't be required to manually start the delayTask, and in fact I receive a exception if I try to do so manually.
The code is being called from the UI thread when a user selects a context menu item in a WPF application, although it works fine if I have the click method specified for the context menu item run this code in a new thread.
public void ContextMenuItem_Click(object sender, RoutedEventArgs e)
{
...
SomeMethod();
...
}
public void SomeMethod()
{
...
SomeOtherMethod();
....
}
public void SomeOtherMethod()
{
...
TcpClient client = Connect().Result;
...
}
//In case you're wondering about the override below, these methods are in
//different classes i've just simplified things here a bit so I'm not posting
//pages worth of code.
public override async Task<TcpClient> Connect()
{
...
Task connectTask = tcpClient.ConnectAsync(URI.Host, URI.Port);
Task delayTask = Task.Delay(1000);
if (await Task.WhenAny(connectTask, delayTask) == connectTask)
{
Console.Write("Connected\n");
...
return tcpClient;
}
Console.Write("Timed out\n");
...
return null;
}
If I change ContextMenuItem_Click to the following it works fine
public void ContextMenuItem_Click(object sender, RoutedEventArgs e)
{
...
new Thread(() => SomeMethod()).Start();
...
}
I predict that further up your call stack, you're calling Task.Wait or Task<T>.Result. This will cause a deadlock that I explain in full on my blog.
In short, what happens is that await will (by default) capture the current "context" and use that to resume its async method. In this example, the "context" is the WPF UI context.
So, when your code does its await on the task returned by WhenAll, it captures the WPF UI context. Later, when that task completes, it will attempt to resume on the UI thread. However, if the UI thread is blocked (i.e., in a call to Wait or Result), then the async method cannot continue running and will never complete the task it returned.
The proper solution is to use await instead of Wait or Result. This means your calling code will need to be async, and it will propagate through your code base. Eventually, you'll need to decide how to make your UI asynchronous, which is an art in itself. At least to start with, you'll need an async void event handler or some kind of an asynchronous MVVM command (I explore async MVVM commands in an MSDN article). From there you'll need to design a proper asynchronous UI; i.e., how your UI looks and what actions it permits when asynchronous operations are in progress.

Something is going wrong with my EventWaithandle, it doesn't change to signaled?

So I'm working on a windows 8 application with some asynchronous methods.
In one particular place I need the aplication to wait for the async method to finish, but it doesn't seem it sends the EventHandle it's state.
Here are the methods that need to work together:
public class Film : Page
private User loggedinUser = new User();
private EventWaitHandle handle = new AutoResetEvent(false);
private dynamic parameters;
protected override void OnNavigatedTo(NavigationEventArgs e)
{
this.parameters = e.Parameter;
LoadFacebookData(parameters);
handle.WaitOne();
LoadUserMovies(loggedinUser.UserName);
}
private async void LoadFacebookData(dynamic parameter)
{
//async code that gets info from facebook whichs determines what user is logged in
handle.Set();
}
private void LoadUserMovies(string username)
{
// irrelevant code
}
the moment the code hits the handle.WaitOne() bit, it stops working completely
In short you are not supposed to use async and wait on something. The standard mistake is to wait on the task returned (deadlock). You did a variation on this: You created an event and waited on it (also deadlock).
Solution: Either embrace async-await or don't do async at all. Can't do both in a mixed style (generally).
If await is available to you, this is a good start:
await LoadFacebookData(parameters);
Get rid of the event.
I suggest you to use the
await LoadFacebookData(parameters);
code line to get the execution continue on the same thread it was started once your async operation finishes.
As far as I can see, there is nothing wrong with the code you have posted. This leads me to believe that the problem is in the code you have commented away. The problem is probably that your code-execution never reaches the line
handle.Set();
This can be because of an exception, or your async code simply never completes. To "deal" with the possibility of an exception, you should probably use the builtin Wait-method of the Task-object, rather than your own EventWaitHandle.
You can remove the EventWaitHandle as a whole, and simply do:
LoadFacebookData(parameters).Wait();
This will propagate any exceptions that occur in the thread within.

Categories

Resources