My application receive some commands from h/w devices in a Thread other than Main(UI) thread.
// start receiver-thread
m_recThread = new Thread(RecThread) { Name = "RS" };
from this thread i want to do some action on the UI Theraad. say one button click!!! i am using
Dispatcher.CurrentDispatcher.Invoke(DispatcherPriority.Normal,
new Action<Vote>(StartThisVote), presidentvote);
but this didnot worked. please let me know who can execute a Command in Main Thread(UI) from this background thread.
From a background thread, the CurrentDispatcher will be null. You need to use the dispatcher associated with the UI that you want to modify. If you don't have access to the control itself from the thread code, you could pass the dispatcher in directly when you start the thread. (Assuming you're on the UI thread when you start the secondary thread.)
As noted in comments, assuming you've just got the one dispatcher (which is very likely) you could use Application.Current.Dispatcher to access it anywhere. (It's harder to test via this static approach, but it's easy to code...)
Alternatively, if you're using C# 5 and .NET 4.5, I'd recommend that you look into async methods, which make a lot of this simpler.
Related
I would like to execute some code from a non-main thread inside the main thread (UI thread) in .Net 6 with C#.
I've tried to use this code:
await Windows.UI.Core.CoreWindow.GetForCurrentThread().Dispatcher.RunAsync(
Windows.UI.Core.CoreDispatcherPriority.Normal,
() => { }
);
This doesn't work, since Windows.UI.Core.CoreWindow.GetForCurrentThread() returns null.
My second try was:
await Windows.ApplicationModel.Core.CoreApplication.MainView.CoreWindow.Dispatcher.RunAsync(
Windows.UI.Core.CoreDispatcherPriority.Normal,
() => { }
);
This fails, because Windows.ApplicationModel.Core.CoreApplication.MainView throws a System.InvalidOperationException.
Another way should be:
await System.Windows.Threading.Dispatcher.RunAsync(
Windows.UI.Core.CoreDispatcherPriority.Normal,
() => { }
);
But the System.Windows.Threading namespace is not available for me, since I'm using .Net 6 and it's not longer supported in it.
Any idea, how I can execute some code from a non-main thread inside the main-thread (UI thread)?
I would like to execute some code from a non-main thread inside the main thread (UI thread) in .Net 6 with C#.
I strongly recommend that you don't. It's far cleaner to have your async methods use something like IProgress<T> to indirectly update the UI as necessary. If you structure your code so that the main thread calls the background threads instead of the background threads manipulating the UI through the UI thread, then you'll end up with a much cleaner design where your logic is less tied to your UI controls.
That said, if you really want to, then the solution is to capture the dispatcher on the UI thread before the background work begins, and have the background work use that dispatcher (not the "current dispatcher") when posting work to the UI thread.
SynchronizationContext is a good solution to switch to the main thread. But it's not implemented for all .Net app types.
For example, for a console app, there is no solution implemented.
But for Windows Forms, WindowsFormsSynchronizationContext works fine.
private SynchronizationContext _synchronizationContext;
Initialization inside, called inside the main thread:
_synchronizationContext = new WindowsFormsSynchronizationContext();
After this, you can call from a different thread:
SynchronizationContext.SetSynchronizationContext(_synchronizationContext);
... here we are in a separate thread
_synchronizationContext.Post(
(state) => {
... this will be executed in the main thread
},
null);
await CoreApplication.MainView.CoreWindow.Dispatcher.RunAsync
(CoreDispatcherPriority.Normal, () =>
{
do something on UI thread
});
I made a short program which has just a button. When the button is pressed, functionA is executed, which also uses functionB and functionC. Inside functionA is a loop which executes functionB and functionC X amount of times. At the end of each loop, the progressbar gets incremented by 1. At the beginning of functionA, before the loop, there's a webservice which pulls data from a website, and passes that onto B and C for processing (data file manipulation and saving to disk).
My problem is that everything works fine, but while functionA is still running, the GUI is stuck, so I can't close/minimize/drag the window around, I have to wait until A is done. I researched and they say I should use BackgroundWorker, but as being a new programmer, I've no idea on how to use it. Can someone give me a simple way to use it?
The progressbar loads fine, but it's just that while the function is running, the whole window is frozen, and I want it so I can move the window around, etc while the program is running, instead of waiting until the function is complete.
Thank you!
Call your function asynchronously like the following and it will not freeze the UI.
private async void BeginProcessingAsync(Data d)
{
//Execute the long running task asynchronously
await Task.Run(() => functionA(d));
//Anything after the await line will be executed only after the task is finished.
anotherFunction(d); // if you have one..
}
To run your task, simply call BeginProcessingAsync(d);. Also, please note: If you're using newer versions of .NET, you might have to use await Task.Factory.StartNew(() => functionA(d)); instead of the above
Overall, you'll want to make sure your GUI doesn't get updated from another thread. Instead, the messages should go to a threadsafe location. For instance, you could have the thread building into something like a database and have the GUI using a timer to look for updated data flags.
There is a question with a lot more detail using delegates here.
Marc's answer was the simplest and best, in my opinion:
///...blah blah updating files
string newText = "abc"; // running on worker thread
this.Invoke((MethodInvoker)delegate {
someLabel.Text = newText; // runs on UI thread
});
///...blah blah more updating files
From Dotnet Perls:
A Background Worker makes threads easy to implement in Windows
Forms. Intensive tasks need to be done on another thread so the UI
does not freeze. It is necessary to post messages and update the user
interface when the task is done.
Also, from MSDN, look at Task-based Asynchronous Pattern (TAP) if you're using C# 5.
The Task-based Asynchronous Pattern (TAP) is based on the
System.Threading.Tasks.Task and System.Threading.Tasks.Task
types in the System.Threading.Tasks namespace, which are used to
represent arbitrary asynchronous operations. TAP is the recommended
asynchronous design pattern for new development.
I working on a WPF GUI app that acts as socket server by using TcpListener class. TcpListener is configured to make an callback when data is received to the listened socket. However the problem is that TcpListener callback comes from another thread and causes following error when I try to touch GUI from the callback:
"Cross-thread operation not valid: Control 'slider' accessed from a thread other than the thread it was created on."
Any ideas how to solve this?
I'm familiar with Qt where this would be done with signal/slot system that can send events to another threads. Is there similar functionality in C#?
You should invoke your code in UI thread. Try to use Dispatcher
Application.Current.Dispatcher.Invoke(Callback):
You need to use the WPF Dispatcher class to invoke the method back to the UI thread - see
this
You want to use the Dispatcher.Invoke method.
If your this is DependencyObject class, you can simply use this:
this.Dispatcher.Invoke((Action)(() =>
{
slider.DoAnythingYouWant();
}));
You cannot directly access GUI elements from a separate (e.g. pulled from the thread pool for async operations or directly created with the Thread class). What you need to do is perform your action through the dispatcher, like so:
Application.Current.Dispatcher.Invoke(DispatcherPriority.Normal,
new Action(() => slider.Text = "mystuff"));
For more information on how the Dispatcher manages threading, see the MSDN link below:
http://msdn.microsoft.com/en-us/library/vstudio/system.windows.threading.dispatcher
Found the solution to make callback function completely in UI thread (CommandHandler is method in MainForm and called from another thread from AsynchronousSocketListener):
void CommandHandler()
{
if (InvokeRequired)
{
/* If called from a different thread, we must use the Invoke method to marshal the call to the proper thread. */
BeginInvoke(new AsynchronousSocketListener.ReadHandler(CommandHandler));
return;
}
else
{
//do UI thread code here
}
}
For those may need working example, stuff was done this way in Basler Pylon 4.0 library example program named PylonLiveView.
In an asynchronous OnMsgRecieved call, if I assign a value directly to a control it is not working.
Then i came to know that it was due to thread unsafe and i got following code to resolve the issue.
Now it is working. But i am not sure what it does practically. Can any one make me to understand it fully?
The code is:-
public void listener_OnMsgRecieved(string aResponse)
{
ShowResponseMessage(aResponse);
}
public void ShowResponseMessage(string aResponse)
{
// InvokeRequired required compares the thread ID of the
// calling thread to the thread ID of the creating thread.
// If these threads are different, it returns true.
if (this.listBox.InvokeRequired)
{
SetTextCallback d = new SetTextCallback(ShowResponseMessage);
this.Invoke(d, new object[] { aResponse });
}
else
{
this.listBox.Items.Add(aResponse);
label.Text = "Response received from Server :";
}
}
When ShowResponseMessage is called on a different thread from that of the UI, the InvokeRequired will return true, then you are using Control.Invoke to send a message to the Windows message queue.
The UI message pump which runs in the UI thread will pull the message and deliver it to the target control, the target control then sees that this is a message requesting that a delegate be invoked and the delegate is invoke by the control, this is now running on the UI thread and therefore the cross threading issue has been resolved.
The trick is that the delegate is not called directly on the non-UI calling thread. Using Windows messages the instruction to execute the delegate is passed to the UI thread which then executes the delegate in response to the message. 'Control.Invoke' uses the Windows [SendMessage][1], Control.BeginInvoke uses the [PostMessage][2] Win32 API to facilitate the message passing.
UI Controls cannot be update/changed from any thread other than the main thread/thread it was created on.
In your case the check InvokeRequired does the check to see if the thread that wishes to change the control is the creating thread, and if not passes the call back to the main thread/creator.
Have a look at How to: Make Thread-Safe Calls to Windows Forms Controls
If you use multithreading to improve the performance of your Windows
Forms applications, you must make sure that you make calls to your
controls in a thread-safe way.
Access to Windows Forms controls is not inherently thread safe. If you
have two or more threads manipulating the state of a control, it is
possible to force the control into an inconsistent state. Other
thread-related bugs are possible, such as race conditions and
deadlocks. It is important to make sure that access to your controls
is performed in a thread-safe way.
It is unsafe to call a control from a thread other than the one that created the control without using the Invoke method.
I am just working on my first GUI application on Windows.
I have a WPF GUI to a small C# utility which copies files. When the button is clicked to copy, I obviously don't want the GUI to hang. So, I fire off a new thread to run the method which copies the files. I assume I'm on track so far and there's no "better" way of doing it in C#?
Now, I have a ProgressBar which I want to appear filled when the thread is done. (It's fine running as indeterminate for now). How do I check when the copying is done?
So, so far I have:
Thread t = new Thread(delegate()
{
po.Organise(inputPath, outputPath, recursive);
});
t.Start();
PBar.IsIndeterminate = true;
And I want something after that that works like:
if (t.Done)
{
PBar.Value = 100;
}
Have a look at the BackgroundWorker class. It supports events like RunWorkerCompleted or ProgressChanged.
Have a look here, too (this is about threading in general + backgroundworker, again).
As already stated, consider the use of the BackgroundWorker class. It was designed for these situations and exposes events suited for what you are trying to accomplish.
Use the ProgressChangedevent to report progress incrementally and the RunWorkerCompleted for when the task finishes. Check the MSDN page for code samples.
Wrap the if (t.Done) block in its own method. Invoke this method from the end of your worker thread.
Also, you might want to give the worker thread a name to make it easier to spot in the debugger.
You need a callback method. This should get you started. It uses an AsyncCallback, which is the best way to tackle this type of issue.
I just looked up an example I've been using for a project and stripped out the code specific to my app:
System.Windows.Forms.MethodInvoker mi = new System.Windows.Forms.MethodInvoker(delegate()
{
// Do your file copy here
});
AsyncCallback ascb = new AsyncCallback(delegate(IAsyncResult ar)
{
this.Dispatcher.Invoke(new ThreadStart(delegate (){
// set progressbar value to 100 here
}), null);
});
mi.BeginInvoke(ascb, null);
The quick and easy hack would be to just update the UI at the end of your anonymous method in your thread. Obviously you can't update it directly, but you can use Dispatcher.Invoke:
Thread t = new Thread(delegate()
{
po.Organise(inputPath, outputPath, recursive);
Dispatcher.Invoke(new Action(()=>{PBar.Value = 100;}),null);
});
t.Start();
As a general Windows programming principal, you have to make calls to update the UI from the UI thread (the one that is processing messages through a message pump).
In Windows Forms, the way that this was done was through the implementation of the ISynchronizeInvoke interface on the Control class, primarily through the implementation of the Invoke method.
With the release of .NET 2.0, it was realized that a better mechanism was needed to marshal calls into the correct context. That's where the SynchronizationContext comes in.
This class abstracts the interface you would use for marshaling calls to different contexts, allowing for specific implementations depending on the context.
So whether or not Windows Forms is the environment, or WPF, one call can be made in the same way across those contexts with the same effect (marshaling the call).
In your particular case, because you are using a closure (anonymous method), you can take advantage of the fact that a SynchronizationContext is available to you (through the static Current property) at the invocation site of the Thread to provide the mechanism to call back to the UI thread from your background thread:
// Get the synchronization context.
// This is in the UI thread.
SynchronizationContext sc = SynchronizationContext.Current;
// Create the thread, but use the SynchronizationContext
// in the closure to marshal the call back.
Thread t = new Thread(delegate()
{
// Do your work.
po.Organise(inputPath, outputPath, recursive);
// Call back using the SynchronizationContext.
// Can call the Post method if you don't care
// about waiting for the result.
sc.Send(delegate()
{
// Fill the progress bar.
PBar.Value = 100;
});
});
// Make the progress bar indeterminate.
PBar.IsIndeterminate = true;
// Start the thread.
t.Start();
Note, if you don't care about waiting for the result of the call back to the UI thread, you can make a call to the Post method instead, which will dispatch the call to the UI thread without waiting for that call to complete.