how to get a task completion notification in non gui thread - c#

Background: I used to call a stored procedure during my Form Load. However, since this resulted in a suboptimal UI experience, I put my SP call in a task of its own inside the Shown event. Since this is typically the last event in the form display process, it resulted in a much better experience than putting stuff in the Form load event. I have:
private void MainForm_Shown(object sender, EventArgs e)
{
dbCheckTask = Task<bool>.Factory.StartNew(RunSPAndCheckStuff());
// both of below run on the GUI thread.
// if I print the thread ID in mycallback it is the GUI thread id
dbCheckTask.ContinueWith(mycallback());
// I also tried below. But obviously, that too runs on the GUI thread
mycallback(dbCheckTask.Result)
}
Because they fire on the GUI thread, my startup form paint is still neither instantaneous nor smooth. How can I get my task complete callback on a non-GUI thread without resorting to events? Whenever the task completes and if something is wrong and only if something is wrong (bool result returned false) then the user gets a message box pop. Until then he could go ahead and do other non database related stuff on the form. Please advise how I can get a task completion callback with task result in a non gui thread. Thank you

All this stuff is addressed best in the Async language extensions you can download here and has the homepage here.
It introduces the async and await keywords to C# and VB that will let you write code that switches back and forth between UI and background threads effortlessly even within a single method. The compiler will convert that to tasks, continuations, error catching etc etc transparantly without you having to worry about any of that. The example that would interest you would be this one:
public async void AsyncSwitchToCPU() {
Console.WriteLine("On the UI thread.");
// Switch to a thread pool thread:
await new SynchronizationContext().SwitchTo();
Console.WriteLine("Starting CPU-intensive work on background thread...");
int result = DoCpuIntensiveWork();
Console.WriteLine("Done with CPU-intensive work!");
// Switch back to UI thread
await Application.Current.Dispatcher.SwitchTo();
Console.WriteLine("Back on the UI thread. Result is {0}.", result);
}
public int DoCpuIntensiveWork()
{
// Simulate some CPU-bound work on the background thread:
Thread.Sleep(5000);
return 123;
}
This even has a go-live license (with some reservations from MS). Very elegant stuff borrowed from F#.
Rgds Gert-Jan

I'd use a BackgroundWorker for this, personally. One way to get your callback to run on the task thread would be to modify your method call and task creation as follows:
private void MainForm_Shown(object sender, EventArgs e)
{
dbCheckTask = Task<bool>.Factory.StartNew(() => RunSPAndCheckStuff(mycallback));
...
}
private bool RunSPAndCheckStuff(Action<bool> callback)
{
bool result = false;
// Do stuff
callback(result);
return result;
}

You should look into using the Asynchronous API's rather than calling the synchronous versions in a background thread:
http://msdn.microsoft.com/en-us/library/system.data.sqlclient.sqlcommand.beginexecutenonquery.aspx
The advantage to that is that no thread will be blocked, and I believe the callback will be called on ThreadPool thread, e.g. NOT on the GUI thread. From there you can marshal any GUI calls back to the GUI thread with Invoke/BeginInvoke.

Why not doing:
Task.Factory.StartNew(()=>WorkerMethod());
And define WorkerMethod() as:
void WorkerMethod()
{
RunSPAndCheckStuff(); // this blocks until finished
DoSomeMoreStuff(); // then this continuous
}
Otherwise please provide more details on what do you want to accomplish.

Related

C# winforms, progress bar will freeze on button click event

So I have my progress bar in my form as 'Marquee' style so it should continuously run, however when I click my button so that the progress will appear, it is froze and does not move, however if I don't hide the progressbar at the start it will run normally.
I only want it to appear when the button is clicked though, any ideas around this?
public Form1()
{
InitializeComponent();
progressBar1.Hide();
}
private void button1_Click(object sender, EventArgs e)
{
progressBar1.Show();
DrawingHandler MyDrawingHandler = new DrawingHandler();
MyDrawingHandler.GetConnectionStatus();
try
{
Operation.RunMacro("shaftCheck.cs");
DrawingEnumerator SelectedDrawings = MyDrawingHandler.GetDrawingSelector().GetSelected();
if (SelectedDrawings.GetSize() == 0)
{
MessageBox.Show("Error, no drawings to export.");
}
else
{
Operation.RunMacro("ExportShaft2.cs");
}
}
catch (Exception)
{
MessageBox.Show("Error");
}
}
}
The most likely reason is that you are doing some kind of slow operation on the UI thread.
There is in most cases only one UI thread, this is the only thread allowed to update the UI, and this can only do one thing at a time. If you are using the UI thread to do some kind of processing it cannot do other things, like updating your UI.
The solution is to put all processing intensive operation on a background thread. For example with Task.Run. But you will need to ensure any called code does not trigger any UI updates.
If you just have a progress bar as part of the dialog it is fairly easy. But it results in the user being able to do other things while you are doing the processing, so you need to be super-careful that all your code is thread safe.
A safer option is usually to show a modal dialog that prevents the user from doing anything else. This greatly reduces the risk of thread safety issues. Typically it would look something like this:
var progressForm = new MyProgressForm();
Task.Run(MyWorkerMethod)
.ContinueWith(t => progressForm.DialogResult = DialogResult.OK, TaskScheduler.FromCurrentSynchronizationContext());
progressForm .ShowDialog();
Is there another property in the progressbar that is a better fit for your needs. Winforms Progress Bar Visible true false in this post it looks like you can change the visibility with the Visibility property.
Your program has only one thread that may update the UI. If you keep this thread busy doing other things, then your UI won't be updated, nor will it respond to operator input.
void LongRunningMethod() {...}
private void OnButton1_Clicked(object sender, ...)
{
this.progressBar1.Visible = true;
this.LongRunningMethod();
this.progressBar1.Visible = false;
}
While LongRunningMethod is being executed, the UI won't respond: the progressbar is not updated, the UI does not respond to user input.
There are two often used methods to solve this.
Old fashioned: use a BackGroundWorker, and let this BackGroundWorker do the LongRunningMethod. The BackGroundWorker sends events when it is finished. You can use that event to hide the progressBar again.
Modern: use async-await. Let a separate Task do the LongRunningMethod.
I won't discuss the BackGroundWorker. If you understand event handling, you will get the gist of it. I'll describe async-await instead.
What really helped me to understand async-await was this interview with Eric Lippert. Search somewhere in the middle for async await.
In this interview Eric Lippert compares async-await with a cook making breakfast. Whenever the cook has to wait for something, like a kettle of water to boil, he doesn't wait idly, no, he looks around to see if he can do something else instead, like insert bread in the toaster. He doesn't wait for the bread to be toasted, he starts scrambling eggs. Later he returns to the boiling water to make tea, or to the toaster to get the toasted bread.
Async-await is similar: whenever your thread has to wait for another process to finish, like writing a file, reading from a database or from the internet, you can let the thread wait idly until the other process completed the task. You could also let the thread do other things, like updating the progressbar and listening to user input. This is called async-await.
Whenever your thread sees an await, it does not wait idly, but it goes up the call stack and execute the code until the caller has an await, up the call stack again and execute the code until the thread sees an await, etc.
Later, when the file-write is finished, or the database data is fetched, or the internet data is downloaded, the thread (or to be precise: any thread from the thread pool) will execute the code after the await.
To be able to use async-await, do the following:
Whenever your program has to wait for another lengthy process, like the examples that I gave above, find the async version of the process: WriteAsync / ReadAsync etc
Define your method async. It is common usage to terminate the identifier of the method with Async: ReadFileAsync, GetProductsAsync, etc. This will make it possible to also have a non-async version: ReadFile, GetProducts.
Return Task<TResult> instead of TResult; return Task instead of void.
There is one exception to this rule: event handlers always return void: no one can await for the result of an event handler
Inside the async method call the WriteAsync / ReadAsync etc. Don't await until you need the results of the async action. await before your async method returns
If the return is Task<TResult>, the result of the await is TResult. If you await Task, the return is void.
So if you need to read lines of text from a file:
private async Task<List<string>> ReadFileAsync(string fileName)
{
using (TextReader textReader = new StreamReader(fileName))
{
List<string> lines = new List<string>();
string line = await textReader.ReadLineAsync();
while (line != null)
{
// a line has been read, add it to the lines, and read the next
lines.Add(line);
line = await textReader.ReadLineAsync();
}
}
}
So if the operator presses a button to read the file and to process the read lines async:
private async Task ProcessLinesAsync(IEnumerable<string> linesToProcess) {...}
private async Task ReadAndProcessFileAsync()
{
string fileName = this.GetFileName();
List<string> lines = await this.ReadFileAsync(fileName);
await this.ProcessLinesAsync(lines);
}
private async void OnButton1_Clicked(object sender, ...)
{
this.ShowProgressBar();
await this.ReadAndProcessFileAsync();
this.HideProgressBar();
}
Note that the event handler returns void instead of Task.
ShowProgressBar is a method that will initialize the progressBar before showing it using this.progressBar1.Visible = true;.
Use other thread to do lengthy calculations
Until now, the UI thread had to wait for another process to finish. Async-await can also be used if you need to do some length calculations while keeping the UI responsive. Use Task.Run to let one of the available threads in the thread pool do the lengthy calculations. Wait for it when you need the results:
private MyResult DoLengthyCalculations()
{
// Do your lengthy calculations here:
DrawingHandler MyDrawingHandler = new DrawingHandler();
MyDrawingHandler.GetConnectionStatus();
try
{
Operation.RunMacro("shaftCheck.cs");
// etc
}
private async Task<MyResult> DoLengthyCalculationsAsync()
{
MyResult result = await Task.Run( () => DoLengthyCalculations();
return result;
}
By the way: this is an example where you have an async and a non-async method: the caller can decide which one he wants to use.
The event handler:
private async void OnButton1_Clicked(object sender, ...)
{
this.ShowProgressBar();
await this.DoLengthyCalculationsAsync();
this.HideProgressBar();
}
Continue processing after the other task started
If you can do something useful instead of awaiting for the task to finish, don't await yet. Await as late as possible: only when you need the result, and before returning.
async Task DoMyWorkAsync()
{
// start reading the file. Don't await, while the file is being read,
// you can do other things:
Task<List<string>> taskReadFile = this.ReadFileAsync();
// because you didn't await, you are free to do something else as soon as
// the thread sees an await:
this.DoSomethingElse();
// you can even start a second task:
Task<MyResult> taskLengthyCalculations = this.DoLengthyCalculationsAsync();
// as soon as you need the results, await for it:
List<string>> readLines = await taskReadFile;
this.ProcessReadLines(readLines);
...
If you want: wait for both tasks to finish:
Task[] allTasks = new Task[] {taskReadFile, taskLengthyCalculations};
await Task.WhenAll(allTasks);
// you can access the return value using property Result:
List<string>> readLines = taskReadFile.Result;
MyResult lengthyCalculationsResult = taskLengthyCalculations.Result;
this.Process(readLines, lengthyCalculationsResult);

What is the right way of calling sync and async methods (api / UI) in one method

In the example below I call a Async method in a Sync method (UI).
In the Async method I call another Async method (api call for example) but I also call other sync methods (for example update combobox). Now I use Invoke((MethodInvoker... for every sync method call. Is this the correct way, can it better? No I also must think to use Invoke((MethodInvoker... when calling a sync method in an async one.
private void control_SelectionValueChanged(Object sender, EventArgs e)
{
Task task = Task.Run(async () => await SomeMethodAsync());
}
private async Task SomeMethodAsync()
{
Invoke((MethodInvoker)(() => SomeMethodA))
bool variable = await SomeOtherMethodAsync()
if ( variable ) Invoke((MethodInvoker)(() => SomeMethodB))
Invoke((MethodInvoker)(() => SomeMethodC))
}
Let's break down what's happening here.
When your control_SelectionValueChanged handler fires, I assume we're running on the UI thread. You then:
Kick off SomeMethodAsync on a thread pool thread via Task.Run. This does not block the UI thread.
As soon as the thread pool thread begins executing SomeMethodAsync you are asking the runtime to marshal you back to the UI thread by calling Control.Invoke. While SomeMethodA is executing back on the UI thread, you are also blocking your thread pool thread at the same time.
You then unblock the thread pool thread and ask it to execute some other async method. The entire operation will stay off the UI thread (unless there's something funky inside SomeOtherMethodAsync, i.e. another Control.Invoke call)
After the await you return to a thread pool thread - this could be the same thread pool thread as prior to the await, or a different one - this is up to the TaskScheduler.
If variable is true, you execute SomeMethodB on the UI thread (while blocking the thread pool thread, again).
Finally, you execute SomeMethodC on the UI thread (while blocking the thread pool thread one last time).
As you can see, most of the time SomeMethodAsync is executing (with the exception of the time spent awaiting SomeOtherMethodAsync, and brief periods between the Control.Invoke calls) you are still using the UI thread, but you are also blocking your thread pool thread. So you're now hogging two threads, mostly with only one of them doing useful work - the other one just sits there and waits.
In addition to being pretty horrendous to read, this is extremely inefficient.
Consider the following rewrite:
private async void control_SelectionValueChanged(Object sender, EventArgs e)
{
try
{
await SomeMethodAsync();
}
catch (Exception ex)
{
// We're an async void, so don't forget to handle exceptions.
MessageBox.Show(ex.Message);
}
}
private async Task SomeMethodAsync()
{
// We're on the UI thread, and we will stay on the UI
// thread *at least* until we hit the `await` keyword.
SomeMethodA();
// We're still on the UI thread, but if `SomeOtherMethodAsync`
// is a genuinely asynchronous method, we will go asynchronous
// as soon as `SomeOtherMethodAsync` hits the its `await` on a
// `Task` that does not transition to `Completed` state immediately.
bool variable = await SomeOtherMethodAsync();
// If you need stronger guarantees that `SomeOtherMethodAsync`
// will stay off the UI thread, you can wrap it in Task.Run, so
// that its synchronous portions (if any) run on a thread pool
// thread (as opposed to the UI thread).
// bool variable = await Task.Run(() => SomeOtherMethodAsync());
// We're back on the UI thread for the remainder of this method.
if ( variable ) SomeMethodB();
// Still on the UI thread.
SomeMethodC();
}
The above is similar (albeit not exactly equivalent) in terms of behaviour, but isn't it much easier to read?
I would advise not mixing them. However the fact that you are in an event handler allows for an exception in the rule where you can have async void
private async void control_SelectionValueChanged(Object sender, EventArgs e) {
SomeMethodA(); //On UI
bool variable = await SomeOtherMethodAsync(); // Non blocking
//Back on UI
if ( variable ) SomeMethodB();
SomeMethodC();
}

Is this a safe way to update the UI Thread in a Windows Forms application?

I'm not super familiar with multithreading, and want to know if this is the safest way to update the UI thread from a different thread. The workflow of my code is as follows:
// this is the button click action
private async void button_Click(object sender, EventArgs e)
{
//do some things to local variables
await create();
}
// this task creates the thing and does all the heavy processing
public Task create()
{
return Task.Run(() =>
{
try
{
//some code
consoleOut(string);
}
catch (Exception e)
{
//do things
}
}
}
// custom logging that prints formatted stuff out to a ListBox
public void consoleOut(String str)
{
if (this.InvokeRequired)
{
this.Invoke(
new MethodInvoker(
delegate() { consoleOut(str); }));
}
else
{
//print stuff
ListBox.Items.Add(str);
}
}
Is this the safest way to update the contents of my ListBox from create Task?
For reference I combined things from these previous questions, but there wasn't a lot of explanation on what the code did, hence my question about thread safety and if there are better ways:
Make wpf UI responsive when button click is performed
Cross-thread operation not valid
This is how I multithread which has worked 100% great for me... though someone will probably get on here and say it's the worst ever...
//start a second thread with parameters in this case
Thread filterThd = new Thread(() => filterLike(FilterTextBox.Text.ToLower(),column));
filterThd.Start();
//somewhere in your thread, it updates the ui like this
Form2 f2= (Form2)System.Windows.Forms.Application.OpenForms["Form2"];
f2.Invoke((MethodInvoker)(() => f2.DataGrid.DataSource = null));
IMHO, there are two problems with the approach you're taking:
You're overcomplicating things - more on that later,
Depending on what the //some code section does you could end-up with a frozen application.
Now, let's tear each part in its own bits.
The over complication is due to the fact that you're mixing two different ways of doing basically the same thing - namely, the Invoke method and a Task, although the Task-based approach is incomplete.
However, the biggest problem is the part with // some code; as I said before, if that part is heavy on the resources (i.e. takes long to run) you could end up with a frozen application because the thread on which that method is running is the UI thread which consumes the UI resources otherwise allocated for the application to process messages and draw controls.
I would split the code into two logical parts:
one that does the processing and
the other one that logs the string to UI
The code should look like this:
private async void button_Click(object sender, EventArgs e)
{
//do some things to local variables
await Task.Run(() =>
{
// some code
})
.ContinueWith(p => ListBox.Items.Add(str),
TaskScheduler.FromCurrentSynchronizationContext());
}
Aside from removing the clutter the code above splits the work into two tasks which can be scheduled differently: the first one can be executed on a background thread and will not affect the UI while the continuation will run on the UI thread due to the restriction passed via TaskScheduler.FromCurrentSynchronizationContext() allowing you to safely access controls and even though it is executed on the UI thread its execution time is very small thus the application won't freeze.

How to marshall work onto the main thread using TPL tasks in C# without causing a deadlock?

I am writing a library that is consuming a resource and for whatever reason the API was designed in a way that events will be raised on different threads but calls of the API has to be done on the main thread.
Let's say the API that I am trying to consume is defined as (I am going to omit event definitions):
public sealed class DodgyService
{
public void MethodThatHasToBeCalledOnTheMainThread() { ... }
}
To consume this API I have added a service on my library called Service (Yup, very original name) that will create a new task (that will run on the main thread as I am specifying a TaskScheduler that has been created from the SynchronizationContext).
Here is my implementation:
public class Service
{
private readonly TaskFactory _taskFactory;
private readonly TaskScheduler _mainThreadScheduler;
public Service(TaskFactory taskFactory, TaskScheduler mainThreadScheduler)
{
_taskFactory = taskFactory;
_mainThreadScheduler = mainThreadScheduler;
}
// Assume this method can be called from any thread.
// In this sample is called by the main thread but most of the time
// the caller will be running on a background thread.
public Task ExecuteAsync(string taskName)
{
return _taskFactory.StartNew(
() => ReallyLongCallThatForWhateverStupidReasonHasToBeCalledOnMainThread(taskName),
new CancellationToken(false), TaskCreationOptions.None, _mainThreadScheduler)
.ContinueWith(task => Trace.TraceInformation("ExecuteAsync has completed on \"{0}\"...", taskName));
}
private void ReallyLongCallThatForWhateverStupidReasonHasToBeCalledOnMainThread(string taskName)
{
Trace.TraceInformation("Starting \"{0}\" really long call...", taskName);
new DodgyService().MethodThatHasToBeCalledOnTheMainThread();
Trace.TraceInformation("Finished \"{0}\" really long call...", taskName);
}
}
Now, if I perform the call of my service (on the main thread) and try to wait on the main thread the application enters a deadlock as the main thread will be waiting for the tasks that has been scheduled to execute on the main thread.
How do I marshall these calls onto the main thread without blocking the entire process?
At some point I thought on performing the detection of the main thread before creating the new task but I don't want to hack this.
For anybody interested, I got a gist here with the code and a WPF app that exhibits the issue.
On btw, the library has to be written on .net framework 4.0
Edit!
I solved my issue following the advice provided by Scott Chamberlain as provided here
as the main thread will be waiting for the tasks
That's a guaranteed deadlock. A task cannot execute on the main thread until it is idle, running the dispatcher loop (aka pumping the message loop). It is that dispatcher loop that implements the magic of getting code to run on a specific thread. The main thread however won't be idle, it is "waiting for the tasks". So the task cannot complete because the main thread won't go idle, the main thread cannot go idle because the task won't complete. Deadlock city.
You must rewrite the code so your main thread won't wait. Move whatever code that appears after the wait call to another task that runs on the main thread, just like that ReallyLongCall().
Do note that you don't seem to get any mileage at all from using tasks, your snippet suggests that none of the code that matters runs on a worker thread. So you might as well call it directly, solves the problem as well.
From your example program:
private void HandleClosed(object sender, EventArgs e)
{
var list = new[]
{
_service.ExecuteAsync("first task"),
_service.ExecuteAsync("second task"),
_service.ExecuteAsync("third task")
};
//uncommenting this line blocks all three previous activities as expected
//as it drives the current main thread to wait for other tasks waiting to be executed by the main thread.
//Task.WaitAll(list);
}
Task.WaitAll is a blocking call, you can't perform blocking calls on the main thread or you will cause deadlocks. What you can do (if you are using Visual Studio 2012 or newer) is use the NuGet package Microsoft.Bcl.Async which gives async/await support to .Net 4.0.
After adding the package change the code to
private async void HandleClosed(object sender, EventArgs e)
{
var list = new[]
{
_service.ExecuteAsync("first task"),
_service.ExecuteAsync("second task"),
_service.ExecuteAsync("third task")
};
//uncommenting this line blocks all three previous activities as expected
//as it drives the current main thread to wait for other tasks waiting to be executed by the main thread.
await TaskEx.WhenAll(list);
}
and your program will no-longer deadlock (it also does not execute any code after await TaskEx.WhenAll(list); but that is because this code is running during the shutdown process and when you await it lets the shutdown continue on processing, if it was placed elsewhere like a click event you would see more normal behavior).
Another option is have a 2nd "Main Thread" and dispatch the work to that. Often when something must be run on "the main" thread are actually saying they require to be run on "a STA Windows Message pumped that the object was initially created on" thread. Here is a example how to to it (taken from here)
private void runBrowserThread(Uri url) {
var th = new Thread(() => {
var br = new WebBrowser();
br.DocumentCompleted += browser_DocumentCompleted;
br.Navigate(url);
Application.Run();
});
th.SetApartmentState(ApartmentState.STA);
th.Start();
}
void browser_DocumentCompleted(object sender, WebBrowserDocumentCompletedEventArgs e) {
var br = sender as WebBrowser;
if (br.Url == e.Url) {
Console.WriteLine("Natigated to {0}", e.Url);
Application.ExitThread(); // Stops the thread
}
}
#HansPassant is correct; by blocking the dispatcher thread to wait on the tasks, you prevent the tasks from ever being executed. The simplest change you could probably make would be to replace Task.WaitAll(list) with:
_taskFactory.ContinueWhenAll(
list,
tasks => { /* resume here */ });
...and then move any code which followed the call to WaitAll() into the continuation. Remember to check the task results and respond appropriately to any exceptions that might have occurred.
But unless there is some tangible benefit to using Tasks that is not apparent in your example code, I would heed Hans' advice and simply forego the Tasks in favor of synchronous calls.

Working with TPL Using Embedded Tasks

I am running a process on a separate thread to facilitate concurrency and a smooth user interface calling
private void ThreadedTestConnection(SqlConnection conn, bool bShowErrMsg)
{
Task<bool> asyncTestConn = Task.Factory.StartNew<bool>
(() => TestConnection(conn, bShowErrMsg));
return asyncTestConn.Result;
asyncTestConn.Dispose();
}
from the UI thread. However, the 'wait' caused by return asyncTestConn is stopping the UI thread being release back to the GUI. I have come up with the following fix. From an event fired from the GUI I have (not including try/catch blocks)
private void SomeClick_Event(object sender, EventArgs e)
{
Task testConnection = Task.Factory.StartNew
(() => UtilsDB.ThreadedTestConnection(mainConn, true));
}
This works. That is, it returns control to the GUI immediately whilst running the test on a seperate background thread. Am I being a very foolish boy in doing this, or is this Okay?
Note: This is a seperate question but related to this one I have not recived a satasfactory answer for.
This is perfectly fine, you are just starting a "fire and forget" task which will run on a thread-pool thread - however in the first example you seem to expect a result (I assume a boolean indicating whether the connection test was successful) - in the second you won't have any - unless your task e.g. raises an event or calls a predefined callback.

Categories