I have an Action delegate:
public static Action SubscribeForTable;
I loaded it with my Objects method
public void SubscribeMe()
{
Parallel.For(0, ACCESS.GetAppCount(), AppCheck);
CheckTable(true);
}
So I have a delegate, which contains the same function but for different objects.
Then I do this:
Parallel.Invoke(SubscribeForTable);
So it launched to run, and I wait...I wait...and nothing happens! The application is stuck! Then I started my debugger.
return to SubscribeMe() function
Parallel.For(0, ACCESS.GetAppCount(), AppCheck); //OK
CheckTable(true); // lets see what is in
Then I looked to this function..
delegate void CheckTableCallback(bool check);
private void CheckTable(bool Subscribed)
{
if (DataGridView1.InvokeRequired) // OK
{
CheckTableCallback Safe = new CheckTableCallback(CheckTable); // OK
DataGridView1.Invoke(Safe, new Object[] {Subscribed}); //HANGS HERE!
}
else
{
....
So it hangs on DataGridView.Invoke. Why so? Hope I have explained my problem correctly.
Control.Invoke, by design, blocks the current thread until the UI thread can process messages.
If you're calling your Parallel.For loop from the UI thread, that will block the UI thread until it completes.
The two cause a condition where one operation (the Invoke call) can't finish until the other completes and free's up the UI thread (Parallel.For), but the second can't complete until the individual work items finish.
You may be able to use BeginInvoke instead of Invoke to avoid the dead lock here, if you're just updating the UI. This will cause the actual method (CheckTable) to run and set the values after the entire operation completes.
Related
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.
I have three threads in total. The first is the main UI thread, which starts a System.Threading.Thread (ExperimentThread), which in turn starts a BackgroundWorker (WorkerThread).
MainThread and WorkerThread both access a shared resource. I synchronise access to this resource with the following object:
private static readonly Object LockObject = new Object();
which I use as follows in the main loop of each thread:
lock (LockObject)
{
// Do something with shared resource here.
}
A cut-down version of ExperimentThread is as follows:
public void RunExperiment
{
while (!bStopThread)
{
lock (LockObject)
{
// Do something with shared resource here.
}
if (bStopThread)
{
break;
}
else
{
Application.DoEvents();
Thread.Sleep(250);
}
}
}
And for completeness here is the DoWork method of WorkerThread:
private void Worker_DoWork(object sender, DoWorkEventArgs e)
{
BackgroundWorker Worker = sender as BackgroundWorker;
for (int X = 0; X < 200; X++)
{
if (Worker.CancellationPending)
{
e.Cancel = true;
return;
}
lock (LockObject)
{
// Do something with shared resource here.
}
}
}
This seems to work fine when both threads are running freely.
At some point the UI thread will terminate the ExperimentThread by setting one of its boolean fields to true and then wait for it to end, as follows:
if (ExperimentThread.IsAlive)
{
ExperimentThread.StopThread = true;
ExperimentThread.Join(); // this line seems to cause the deadlock?
}
As soon as Join() is called, a deadlock occurs on the shared resource being accessed by ExperimentThread and WorkerThread, and my application hangs indefinitely. This happens maybe 9 out of 10 times.
If I remove ExperimentThread.Join() from the code snippet above, the deadlock never occurs, and ExperimentThread appears to terminate gracefully (it then goes on to terminate WorkerThread by calling CancelAsync()).
Any ideas what could be the problem here?
(P.S. I've been using Console.WriteLine() to determine when locks are taken and released, which is what has lead me to believe there's a deadlock. Is there a better to determine this, I could be wrong?)
Is there a better to determine this, I could be wrong?
A better way to check this is to use something like the Concurrency Visualizer available in higher level SKUs of Visual Studio. It will allow you to see exactly what has locked each thread, and what handles threads are waiting on, etc.
As for the exact reason you are getting a deadlock - there isn't enough code to determine this, but common issues are:
ExperimentThread and the main thread (with the Join() call) are both locking on the same object - ie: within a lock(LockObject) statement.
ExperimentThread is using Control.Invoke to marshal a call back onto the UI thread. Since the UI thread is blocked (waiting on the Join()), it can never process messages, which will prevent ExperimentThread from completing.
That being said, in general, I would recommend using Task or Task<T> instead of a new Thread if you're using .NET 4 or higher. Task provides a much nicer API for working with threads, including allowing continuations instead of blocking. C# 5 extends this to even allow you to asynchronously wait for the task to complete.
I have a method which is called on a different thread than UI thread.
When this method is called the control is gone , I mean nothing happens.
The code is like below:
private void MainForm_NewMeasurementState(Measurement measurement)
{
try
{
if (InvokeRequired)
{
// we were called on a worker thread
// marshall the call to the user interface thread
this.Invoke(new Action<Measurement>(MainForm_NewMeasurementState), new object[] { measurement });
return;
}
// some other code
}
The control comes in the if statement but then I don't know what happens, the other code is never called.
Any help will be appreciated.
It could be that your main thread is blocked, perhaps because it is waiting for your code to complete (i.e. your code is deadlocked because two threads are waiting for each other).
Try to find out why the main UI thread is blocked, or else use BeginInvoke instead of Invoke.
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.
I've inherited code where BeginInvoke is called from the main thread (not a background thread, which is usually the pattern). I am trying to understand what it actually does in this scenario.
Does the method being called in the BeginInvoke get in line of messages that come down to the window? The docs say asynchronously, so that is my assumption.
How does the framework prioritize when to kick off the method called by BeginInvoke?
Edit: The code looks like this:
System.Action<bool> finalizeUI = delegate(bool open)
{
try
{
// do somewhat time consuming stuff
}
finally
{
Cursor.Current = Cursors.Default;
}
};
Cursor.Current = Cursors.WaitCursor;
BeginInvoke(finalizeUI, true);
This is happening in the Form_Load event.
edit
Now that we see the code, it's clear that this is just a way to move some initialization out of Form_Load but still have it happen before the user can interact with the form.
The call to BeginInvoke is inside Form_load, and is not called on another object, so this is a call to Form.BeginInvoke. So what's happening is this.
Form_Load passes a delegate to Form.BeginInvoke, this puts a message in the form's message queue that is ahead of all user input messages. It sets the cursor to a wait cursor.
Form_Load returns, and the rest of form initialization is allowed to complete, the form most likely becomes visible at this point.
Once the code falls into the message pump, the first thing is sees in the queue is the delegate, so it runs that.
as the delegate completes, it changes the cursor back to the normal cursor, and returns
profit!
original post below
I depends on the object that you call BeginInvoke on. If the object is derived from Control then Control.BeginInvoke will run on the thread that created the control. See JaredPar's answer.
But there is another pattern for the use of BeginInvoke. if the object is a delegate, then BeginInvoke runs the callback on a separate thread, one that may be created specifically for that purpose.
public class Foo
{
...
public Object Bar(object arg)
{
// this function will run on a separate thread.
}
}
...
// this delegate is used to Invoke Bar on Foo in separate thread, this must
// take the same arguments and return the same value as the Bar method of Foo
public delegate object FooBarCaller (object arg);
...
// call this on the main thread to invoke Foo.Bar on a background thread
//
public IAsyncResult BeginFooBar(AsyncCallback callback, object arg)
{
Foo foo = new Foo();
FooBarCaller caller = new FooBarCaller (foo.Bar);
return caller.BeginInvoke (arg);
}
This pattern is one reason that BeginInvoke is called from the main thread rather than from a background thread.
In the case BeginInvoke is called on a UI thread it will still go through the process of posting a Windows Message to the message queue where the message will wait to be processed. The delegate will run when the message is processed. This message is not prioritized in any way that's different than it being called from the background thread.
In this scenario I suspect the call looks like:
private void Button1_Click(object sender, ButtonClickEventArgs e)
{
Control.BeginInvoke(new MethodInvoker(()=> /* code etc. */));
}
What's happening is that some code will run on on a threadpool thread, and update the control on the thread that created the control whereas if Control.Invoke was used, some code would run on the thread that created the control, and update the control on that thread as well.
Prior to widespread BackgroundWorker use, you had to synchronize back to the UI thread before doing any operations on Controls created on the UI thread (i.e. pretty much every Control).
There's a pretty good reference example here down in the "Thread-Safe Calls to a Windows Forms Control" section.