Why WPF app not closing after Client Proxy Async Call to WCF? - c#

Hello I have next problem with WCF. I generate my client proxy class with "task-based" async mode.
With sync methods all works good, but when I call async method (void or not - irrelevant) and close my WPF MainWindow (through cross on title bar), window closed but process not killed. And this happen only after async calls.
i try this:
var client = new Service.ServiceClient();
await client.syncWithDevicesAsync();
client.Close();
and with 'using':
using (var client = new Service.ServiceClient())
{
await client.syncWithDevicesAsync();
}
I've seen similar questions, but I could not understand them, please explain why this is going. Thx for help.
UPD: In debug thread window I saw when I call async method, created 4 threads, but after response released only 3.. GC.Collect() in close window event not help.
UPD2: after Julian answer I try next:
private async void Button_Click(object sender, RoutedEventArgs e)
{
var proxy = new ServiceReference1.ServiceClient();
var photo = await proxy.getEmployeePhotoAsync(12);
label.Content = photo.Length; //everything is good, label show correct size. So the asynchronous method is completed?
proxy.Close();
//Environment.Exit(0); //- if uncomment window freeze forever. label nothing show.
}
and try this:
await Task.Run(async () =>
{
var photo = await proxy.getEmployeePhotoAsync(12);
Application.Current.Dispatcher.Invoke(() =>
{
label.Content = photo.Length;
});
});
UPD3: Oh..Now I am completely stuck. I download github example by Mahesh Sabnis. and the same behavior, the process hangs in task Manager after closing. Can someone tested at itself?

Using async methods with Task.Run:
queues that Task for execution on a threadpool thread. Threads execute in the
context of the process (eg. the executable that runs your application)
thus it's not running on the UI Thread (SO)
I presume that in your case some async method is still running (probably even looping) in the background after you have closed the WPF window and the UI thread stopped. Consequently the process is still running.
You could pass a CancellationToken to the background task(s) and then call Cancel in the application exit event.
As a last resort you could also call the System.Environment.Exit() method which terminates the process.

I'm not sure anyone else face this, but still I will write an answer. I first encountered this..
Problem was in my pc or VS2013.. I reboot my pc and all work with:
private async void Button_Click(object sender, RoutedEventArgs e)
{
var proxy = new ServiceReference1.ServiceClient();
var photo = await proxy.getEmployeePhotoAsync(12);
label.Content = photo.Length;
proxy.Close();
}

Related

Async action hangs/deadlocks, why? (not waiting for Result, nor ConfiguringAwait)

First, sorry for yet another "why my async action hangs" question but I believe this question is different enough.
Surveying dozens of similar questions, the problem of async action deadlock is either in locking yourself out (.Result), using limited resources or using library components incorrectly (web requests seems popular). In the following example, I cannot find any from above:
private async Task ExecuteAsync(Task<int> task)
{
// entering on current thread, that is the main UI thread
await task // execute "task" asynchronnously (on a different thread)
.ConfigureAwait(false); // when done, no need to return to main thread
MessageBox.Show("success"); // succes indicator
}
public MainWindow() //wpf window ctor
{
InitializeComponent();
this.Loaded += MainWindow_Loaded;
}
private void MainWindow_Loaded(object sender, RoutedEventArgs e)
{
var task = new Task<int>(() => 42); // make an Action wrapping sychronnous method
// fire and forget, never caring for .Result, disard even the task
var _ = ExecuteAsync(task).ConfigureAwait(false);
}
I have commented the sample with my best try on exaplaining how things (should) work, but something in my explanation must be wrong. Even though MainWindow ctor does not deadlock, the Action () => 42 is never executed and "success" message is not shown. After some debugging I managed to fix the sample (using Task.FromResult), but I am still not sure what is wrong with it as it is now and even more importantly why.
What is the error in my reasoning and why was the action never executed/finished?
You did not start the task! You only declared it. Simply awaiting it does not "fire" it.
private async Task ExecuteAsync(Task<int> task)
{
// at first do start the task
task.Start();
await task.ConfigureAwait(false);
MessageBox.Show("success");
}
Note that ConfigureAwait(false) does not guarantee that execution will be continued on a different thread. It only says that you don't need it to be resumed on the original thread. And resuming UI work (like MessageBox.Show()) on a non-UI thread is not recommended.
As NineBerry pointed out, if you want to wrap a synchronous method and let it run on a different thread, you should use Task.Run():
var task = Task.Run(() => YourSynchronousCall());

Open a custom busy indicator while a main window is busy or doing some task

My application is based on WPF.
Task is I need to show a custom busy indicator while something is working in the main window ( because the app UI will be freezed untill it complete the task). So what I particularly want is as below
// Code in main window
CustomBusyIndicator.ShowDialog();
//....
//..code that takes time
//....
CustomBusyIndicator.Close();
So I must implement a window which must be flexible to call anywhere in my main application to indicate busy.
Here two points should be kept in mind,
1. When i show CustomBusyIndicator, in background the main window should be running it's task
2. When i show CustomBusyIndicator, the CustomBusyIndicator should be always on top of main window, user must not be able to use the main window, if he switch to other application using Start+tab or something and again when he switch back to my application,the CustomBusyIndicator should be on top(if it is not closed).
When the task is completed I should be able call just close() method to close the CustomBusyIndicator from the main window as shown in code.
Easy to solve
public async void Button1_Click(Object sender, RoutedEventArgs e)
{
// get a task for the dialog, but do not await here its completion
var dialogTask = CustomBusyIndicator.ShowDialogAsync();
// await the completion of the lengthy operation
await SomeLengthOperationAsync();
// close the dialog
CustomBusyIndicator.Close();
// now await the completion of the dialog task
await dialogTask;
}
and the extension is
public static class WindowExtensions
{
public static async Task<bool?> ShowDialogAsync( this Window window )
{
await Task.Yield();
return window.ShowDialog();
}
}
If you don't know how to work with async await, just move your long running logic in a backgroundworker. There are several options for making the backgroundworker communicate without problems with the main GUI thread.
Based on your question and your level of experience I think you are way over your head with async wait. But Rufo's solution is fine too.
Google is your friend, There is a lot of information about using the backgroundworker and about async await too. It will just take a bit longer to fully grasp the potential of async await. Async await is btw not a solution for everything. I ran into a situation today where I ran in a database with EF6 that simply says it does not support async operations. Works perfectly well with sql server but this was pervasive. Total dissapointment because now me too have to use a backgroundworker where my first idea was async await.
The idea behind async await, is that the gui thread is not blocked if you are doing a long running task. It is more like a waitpoint where it will continue if that long operation is finished.
Other options are to use RX, but that difficulty level increases again.
Use the backgroundworker and you are fine, and your gui is never blocked. You can even cancel the work of the backgroundworker. Excellent solution for you.

Async method won't return when called

I'm having a bad time with this. I'm trying to make a async method that returns the contents of a local file as string. This is my approach:
private static async Task<string> ReadContentsAsString(string fileName)
{
var uri = new Uri(string.Format(#"ms-appx:///{0}", fileName));
var file = await StorageFile.GetFileFromApplicationUriAsync(uri).AsTask().ConfigureAwait(false);
var stream = await file.OpenStreamForReadAsync().ConfigureAwait(false);
using (var streamReader = new StreamReader(stream))
{
return await streamReader.ReadToEndAsync();
}
}
Unfortunately, after the execution reaches the end of my method, the application waits forever. It hangs completely. It's being called at the very beginning, when the splash screen still shows (Windows Phone 8.1)
What do I miss?
I suspect that further up your call stack, your code has a call to Task.Wait or Task<T>.Result. This can cause a deadlock that I describe on my blog.
In summary, what happens is that when await is used on a task, by default it will capture the current "context" and use that context to resume the async method. In this case, the context is the UI context, which is associated with the single UI thread. If code further up the call stack is calling Wait or Result, then it's blocking the UI thread, which prevents the async method from finishing.
Your method is working as it should. I suspect that you are encountering this issue while debugging.
I also have noticed (sometimes) such a behaviour when debugging asyc method (here is a link to the question) - the program never returns from the method and just hangs - I don't know the exact reason of this. To test it just try to run your method like this - for example upon button click:
private async void firstBtn_Click(object sender, RoutedEventArgs e)
{
Debug.WriteLine("Before method");
string readValue = await ReadContentsAsString("TextFile1.txt");
Debug.WriteLine(string.Format("Read value: {0}", readValue));
}
As I've tested on device - it should work, but if I set a breakpoint inside your method - it will hang.

Label takes long time to change [duplicate]

This question already has an answer here:
Label won't change color until after code is finished executing
(1 answer)
Closed 8 years ago.
I have a problem with my winform app in C#.
In program, i have a label as statusbar and a method like this:
private void btnProcess_Click(object sender, EventArgs e)
{
lblStatus.Text = "Please wait...";
/*
Code here
*/
}
my code process taking a few second but after processing the code, text of label will change and i want it happening before that.
Note: I am an amateur in programming and i cant understand english very well, please explain your solution simply. thank you.
You may be able to hack this using a repaint event by calling Update or Refresh, but the real solution is using a BackgroundWorker for longer operations.
This is not easy stuff, you should find a tutorial for it in a language you understand perfectly.
In winform application (but also in all GUI application) it's not recommended execute long task in the GUI thread. For solving your problem you must use Thread(here you can find the complete mdsn reference).
If you want update the Label from another Thread you' ll do a Cross threading operation. For more information take a look to this question
All the code is always ran and completed before any changes are made to the UI. This is just the basic logic of WinForms and WPF.
You can use "BackgroundWorker", so the longer code is run on another thread. This way you can freely edit the UI-elements while the longer code is still running.
If you are using .Net 4.5, you can use await and async rather than BackgroundWorker.
You would create an async method that returns a Task, and inside that method use Task.Run() to start the background work.
Here's an example. You'd do all the slow work in the lambda passed to Task.Run() where I've commented "Do all your slow work here":
private async void btnProcess_Click(object sender, EventArgs e)
{
lblStatus.Text = "Please wait...";
await doSomeWorkAsynchronously();
lblStatus.Text = "Work completed";
}
private async Task doSomeWorkAsynchronously()
{
await Task.Run(()=>
{
// Do all your slow work here.
Thread.Sleep(5000); // Simulate slow work.
});
}
I think this is a bit easier than using BackgroundWorker.
Note that if all your "slow" methods were already async (e.g. if you are using asynchronous file I/O) then you might just be able to await each of your async operations rather than having to create your own task via Task.Run().
You can also return a value from the background task. Suppose you wanted to return a string with which to update the label when the background task had completed. You could do that as follows:
private async void btnProcess_Click(object sender, EventArgs e)
{
lblStatus.Text = "Please wait...";
lblStatus.Text = await doSomeWorkAsynchronously();
}
private async Task<string> doSomeWorkAsynchronously()
{
return await Task.Run(()=>
{
// Do all your slow work here.
Thread.Sleep(5000); // Simulate slow work.
return "The task completed.";
});
}

Silverlight and problems with async call

I have some code that works as follows:
App.xaml calls a SetUp() method which populates a local collection using async calls and exposes the collection as a public property.
That's all good.
Now I make an instance of the first page in my Silverlight app like so
private void Application_Startup(object sender, StartupEventArgs e)
{
this.RootVisual = new Summary();
}
In the constructor of Summary() I expect those async calls to have been complete and my collection to be filled but the async calls have not yet complete. Even if I do a Thread.Sleep(100000....) before i make an instance on Summary() this is the case
And the thing is that until the constructor of Summary() is exited and the UI displayed to the user my async calls do not get kicked off!
What!!!
Is there anything I can do about that or is that just the way asyn calls work i.e. they wait until the current until of work finished before firing?
This is how I work round this situation (I'll use simple string download as an example):-
private void Application_Startup(object sender, StartupEventArgs e)
{
WebClient web = new WebClient();
web.DownloadStringCompleted += (s, args) =>
{
// Do stuff with args.Result);
this.RootVisual = new Summary();
};
web.DownloadStringAsync(new Uri("SomeUrl.txt", UriKind.Relative));
}
Note that the construction of Summary and the assignment to RootVisual are defered until the asynchronous download is complete.
Silverlight was specifically designed to not have any blocking operations -- that's why you have to do async in the first place. What you really have to do is make your app run properly while waiting for the async completion handler to execute.
This is by design. The alternative would be that the user has to wait longer before he sees anything at all.
If you really want to prevent showing an incomplete summery then first shown another page with 'waiting' or a progress bar. Fire the async events from that page or its parent. Then show the Summary when the async call returns.
To deal with an incomplete Summary you might want to use ICommand
I know this is an old thread, but for all following reader i want to provide my experience with a similar problem. If i understood you correctly - the reason why your async calls do not complete is because you block the main thread. I ran into the same problem, if you block the main thread none of the other threads continue. The solution was to do the async calls inside a backgroundworker and show, like pauldendulk said, a waiting - page. Use Debug.WriteLine() to monitor the process in the output.

Categories