I am working on a project of my company in which they used Dispatcher.Invoke() in many places.If I am using BeginInvoke instead of Invoke then the Synchronisation between threads working fine but in case of Invoke the application is freezing and even not entering the execution to the delegate method also. Does anybody have any idea why it is happening like this?
Any answer will be appreciated.
Sample Code for Invoke used in the Project:
Dispatcher.Invoke(DispatcherPriority.Send,
new DelegateMethod(MethodtoExecute));
private delegate void DelegateMethod();
void MethodtoExecute()
{
try
{
}
catch (Exception /*ex*/)
{
}
finally
{
}
}
Dispatcher.Invoke executes synchronously on the same thread as your application, so whatever you invoke is able to block the main application thread. Dispatcher.BeginInvoke executes asynchronously, so it doesn't tie up the main application thread while executing.
Since you are using DispatcherPriority.Send, which is the highest dispatcher priority level, whatever you are invoking gets run before anything else, including rendering the screen or listening for events. I'd recommend switching that to DispatcherPriority.Background, which runs at a lower priority than Render and Input. See this page for a list of the DispatcherPriority levels and their execution order
I'd highly recommend you look at the answer posted here
Related
I have a multi-threaded UI application that starts numerous background threads. A lot of these threads execute code that looks as follows:
public void Update(){
if(Dispatcher.HasShutdownStarted()) return;
Dispatcher.Invoke(()=>{...});
...
}
Then I sometimes may have a thread execute the following code
pubic void Shutdown(){
if(Dispatcher.HasShutdownStarted()) return;
Dispatcher.InvokeShutdown();
}
The problem is that sometimes one thread executes Dispatcher.InvokeShutdown() AFTER another thread executed Dispatcher.HasShutdwonStarted() but before it got to Dispatcher.Invoke(()=>{...}). Which means, that there will be a thread trying to execute a lambda on the Dispatcher once the Dispatcher has begun to shut down. And that's when I get exceptions. What is the best solution to this?
The problem you face is that the HasShutdownStarted is checked, before the code inside the Invoke is executed (because it's queued on the dispatcher)
I think a better way is to check it inside the invoke, this way you don't need any locks.
public void Update(){
Dispatcher.Invoke(()=>
{
if(Dispatcher.HasShutdownStarted()) return;
...
});
}
With the help of others I managed to come up with the following solution to my problem and thought I'd share it. Calling Dispatcher.Invoke(...) after Dispatcher.InvokeShutdown() will always lead to a TaskCancelationException being thrown (as far as I can tell). Thus, checking Dispatcher.HasShutdownStarted inside of the Invoke method will not work.
What I did was create an application global CancellationToken by creating a static CancellationTokenSource. I now invoke the Dispatcher as follows:
Dispatcher.Invoke(()=>{...}, DispatcherPriority.Send, GlobalMembers.CancellationTokenSource.Token);
Then, when I wish to invoke shutdown on my dispatcher, I do the following:
GlobalMembers.CancellationTokenSource.Cancel();
Dispatcher.InvokeShutdown();
If by any chance I try to run Dispatcher.Invoke(()=>{...}, DispatcherPriority.Send, GlobalMembers.CancellationTokenSource.Token) after cancelling the global token and after invoking Dispatcher.InvokeShutdown(), nothing happens as the token is already cancelled and thus the action is not run.
I'm a bit of a newbie at this but I am trying to get the UI on a Reversi game to run on a different thread to the move selection part but I am having some trouble calling the thread on the button click
private void playerMoveOKButton_Click(object sender, EventArgs e)
{
ReversiT.Invoke();
}
public void ReversiT() {...}
If you're trying to create a new thread, you can do something like this:
Thread thread = new Thread(ReversiT);
thread.Start();
Invoke is used for a different purpose though. It is used to run a method on a specific thread (for instance, if you run a piece of code on a separate thread but want to make UI changes, you will want to use Invoke to make those changes on the UI thread)
I would create a BackgroundWorker to handle everything for me, setting it's DoWork event to call your move method (making sure that your move method doesn't touch the UI, or if it has to, invoking the controls on the UI thread).
I'd also set up a method to update the UI on the BackgroundWorker's RunWorkerCompleted event.
Now on your button click event above, call the BGW's RunWorkerAsync() method.
You can not invoke a method like that. You can only invoke delegates. Also, calling Invoke doesn't spawn a new thread.
You can read this tutorial about delegates, and this one about threads. Also, your question leaves much space for discussion:
What do you expect from using threads?
Have you considered different options for doing background work?
etc.
Use following
this.Invoke(ReversiT);
I think you need to think about that you are actually trying to achieve here. Running code on a separate thread in a UI is a technique used to stop the UI from hanging. However, some tasks simply have to occur on the UI thread and so can't be run from another thread.
You need to break your logic out such that you can identify which parts need to run on the UI thread (anything that interacts with a control on your UI) and thus anything that can run on a separate thread.
You would end up with code like (as an example):
private void playerMoveOKButton_Click(object sender, EventArgs e)
{
//thread is merely used as an example
//you could also use a BackgroundWorker or a task
var thread = new Thread(NonUiLogic);
thread.Start();
}
private void NonUiLogic()
{
...
//execute logic that doesn't touch UI
...
BeginInvoke(ReversiT);
}
public void ReversiT() {...}
Once you have been through that exercise you may find that there is actually very little that can happen outside of the UI thread and so you really have nothing to gain from using threads.
Web Developer here and need some advice on how to achieve what must be a common requirement in Windows Forms.
I have a windows client app that calls a business object in a separate project to perform some long running tasks. Difference to other examples is that the process live in another class library i.e. Business.LongRunningTask();
I have a list box in the client that I would like to have logged to by the task. I can run the process on the UI thread passsing in the instance of the textbox and calling Application.DoEvents() when I log to the textbox from within the task. All fine, but not elegant and would prefer not to call Application.DoEvents();
If I run the long running process on a separate thread using delegates I cannot access the textbox or delegates created in the windows client form which rules out BeginInvoke calls.
Surely this is bad design on my part and would appreciate some feedback.
You're looking for the BackgroundWorker class.
To execute a time-consuming operation in the background, create a BackgroundWorker and listen for events that report the progress of your operation and signal when your operation is finished.
You can find a complete example here: http://msdn.microsoft.com/en-us/library/b2zk6580(v=VS.100).aspx#Y1351
I can run the process on the UI thread
passsing in the instance of the
textbox and calling
Application.DoEvents() when I log to
the textbox from within the task.
Yes, you could also pass in an instance of ILoggingINnterface that you have used to put in the code to write to the text box FROM WITHIN THE UI and thus have taken care of all the nice BginInvoke stuff ;)
If I run the long running process on a
separate thread using delegates I
cannot access the textbox or delegates
created in the windows client form
which rules out BeginInvoke calls.
Ah. No. You just most invoke back to the dispatcher thread then you can access all the UI elemente you like.
Yeah, avoid Application.DoEvents().
To marshall the call back onto the UI thread, call this.Invoke(YourDelegate)
To access UI elements from a different thread, you can use control.Invoke to call a delegate on the owning thread.
I used this at one point to create a live log screen which was updated from a timer while a different worker thread was running. Heres a simplified version:
public class DifferentClassLibrary
{
public delegate void StringDataDelegate(string data);
public event StringDataDelegate UpdatedData;
public void DoStuff()
{
if (UpdatedData != null)
{
Thread.Sleep(10000);
UpdatedData("data");
}
}
}
And in the winform:
public void UpdateTextBoxCallback(string data)
{
if (uiTextBoxLiveLogView.InvokeRequired)
{
uiTextBoxLiveLogView.Invoke(new DifferentClassLibrary.StringDataDelegate(UpdateTextBoxCallback), data);
}
else
{
uiTextBoxLiveLogView.Text += data;
}
}
void Main()
{
DifferentClassLibrary test = new DifferentClassLibrary();
test.UpdatedData += UpdateTextBoxCallback;
Thread thread = new Thread(new ThreadStart(test.DoStuff));
thread.Start();
}
I have a windows forms application
on which I need to use a for loop having a large number of Remote Calls around 2000 - 3000 calls,
and while executing the for loop, I loose my control on form and form controls, as it becomes a large process and some time it shows "Not Responding" but if I wait for a long it comes back again, I think I need to use some threading model for that, is there any idea, how can I proceed to solve the issue?
You need to perform the long running operation on a background thread.
There are several ways of doing this.
You can queue the method call for execution on a thread pool thread (See here):
ThreadPool.QueueUserWorkItem(new WaitCallback(YourMethod));
In .NET 4.0 you can use the TaskFactory:
Task.Factory.StartNew(() => YourMethod());
And in .NET 4.5 and later, you can (and should, rather than TaskFactory.StartNew()) use Task.Run():
Task.Run(() => YourMethod());
You could use a BackgroundWorker for more control over the method if you need things like progress updates or notification when it is finished. Drag the a BackgroundWorker control onto your form and attach your method to the dowork event. Then just start the worker when you want to run your method. You can of course create the BackgroundWorker manually from code, just remember that it needs disposing of when you are finished.
Create a totally new thread for your work to happen on. This is the most complex and isn't necessary unless you need really fine grained control over the thread. See the MSDN page on the Thread class if you want to learn about this.
Remember that with anything threaded, you cannot update the GUI, or change any GUI controls from a background thread. If you want to do anything on the GUI you have to use Invoke (and InvokeRequired) to trigger the method back on the GUI thread. See here.
private voidForm_Load(object sender, EventArgs e)
{
MethodInvoker mk = delegate
{
//your job
};
mk.BeginInvoke(callbackfunction, null);
}
private void callbackfunction(IAsyncResult res)
{
// it will be called when your job finishes.
}
use MethodInvoker is the easiest way.
Obviously, you need to use background threads. I suggest you read this free e-book.
I am using a background thread to initialize an instrument over USB. The UI hangs when I try to open the device. I would expect the background thread to pause when calling Open on the device, but not the UI thread. I am testing this with no UI interaction from the background thread. I don't know how to debug the problem, and it's too broad a question, but perhaps someone has seen something like this before. There is nothing wrong with the ActiveX interop as far as I know, the device works correctly. This is the general approach:
using System;
using FancyVoltmeterLibrary;
namespace SOQuestion
{
public class MeterClass
{
private FancyVoltmeter meter;
private Thread meterThread;
public MeterClass()
{
// Create instance of ActiveX/COM object.
meter = new FancyVoltmeter();
meterThread = new Thread(UpdateMeter);
meterThread.Name = "Meter Thread";
meterThread.Priority = ThreadPriority.Normal;
meterThread.IsBackground = true;
meterThread.Start();
}
private void UpdateMeter()
{
while(true)
{
Thread.Sleep(1000);
if(!meter.IsOpen())
{
// Meter may be powered off here.
// The call to Open takes about 1 second.
// UI hangs during the call???
meter.Open();
}
// code to read meter goes here.
}
}
}
}
Edit: Perhaps unclear what I meant. By 'hang' I should say 'freezes momentarily'.
Does meter require running in an STA? Is the call to Open() actually being marshalled back to the UI thread for this reason?
You can verify this is true by looking at the callstack of the hung UI thread in the debugger.
How long time does the instantiation of the FancyVoltmeter take? Could it be that it is not the Open method that causes the UI freeze, but creating the COM object (which is done on the UI thread)?
If that turns out to be the case, moving the creation of this object to happen on the new, separate worker thread should take care of the problem.
Edit: I saw now that you already found this out in your comment to Michael...
I would suggest you wrap the call to meter.open() in a separate method, and call that method from within the updateMeter() method using Invoke() or BeginInvoke() construct on the form or parent control. Doing this will marshal the action back on to the UI thread and should execute gracefully. I hope this helps.
Consider using a BackgroundWorker for this task.