How do I run a method in the background for c# wpf? It is a packet sniffing method which will update the UI whenever new data is received, do I have to use dispatcher.invoke?
You could use the Dispatcher or the BackgroundWorker: See Build More Responsive Apps With The Dispatcher
There are a lot of ways to do this in WPF, but here's one very simple way using Task to do the work on another thread and then dispatching the UI updating back to the main thread:
Task.Factory.StartNew(() =>
{
// some work (packet sniffing)
// update UI
this.Dispatcher.BeginInvoke(new Action(() =>
{
// update my controls here
}));
});
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
});
In C# we know there is multiple Background thread ... so like that can we create multiple UI thread?
and Multiple UI thread helps to update data in observation collection without freeez?
if No. what is the best way to get data from webservice and update to observation collection..
Code:-
Thread lthrThread = new Thread((ThreadStart)delegate
{
string Data = DataFromServer()
this.Dispatcher.BeginInvoke(new Action(() =>
{
UI freeze here for 5 -10 seconds
}));
});
lthrThread.SetApartmentState(ApartmentState.STA);
lthrThread.Start();
UI thread is main thread.You cannot copy of it.If you call your data on ui thread,your application user interface will not respond until it ends.So,you need to create background thread or task that handles data call from webservices.When you get data from webservice pass it to the main thread (UI). You can use Dispatcher for it.
Application.Current.Dispatcher?.BeginInvoke(new Action(() => {
// Pass data to UI here.
}));
or you can use async Task which will be more convenient.
In a WPF application (C#, .NET 4.0, VS 2013), the following code (called from UI thread) freezes UI thread for 1 second:
new Thread(new ThreadStart(() =>
{
Dispatcher.BeginInvoke(new Action(() =>
{
Thread.Sleep(1000);
}));
})).Start();
The Thread.Sleep() is a placeholder. In actual code it will access some UI element and do some time consuming calculation. That also runs on UI thread!
Shouldn't it be run in another thread other than the UI thread? What have I missed?
Dispatcher.BeginInvoke is designed to push operations (via a delegate) onto the UI thread. You have told it to push a Thread.Sleep(1000) onto the UI thread, so yes: the UI thread will freeze.
From MSDN
For example, a background thread that is spun off from the main UI thread cannot update the contents of a Button that was created on the UI thread. In order for the background thread to access the Content property of the Button, the background thread must delegate the work to the Dispatcher associated with the UI thread. This is accomplished by using either Invoke or BeginInvoke. Invoke is synchronous and BeginInvoke is asynchronous.
If you wanted to do the work in the background... you were already on a background thread (before calling Dispatcher.BeginInvoke).
I suspect what you should be doing here is:
use .Invoke to gather values from the UI into the worker
do the processing on the worker
use .Invoke or .BeginInvoke to update the UI
Dispatcher.BeginInvoke executes operations on the main thread. Use this to execute on your thread:
new Thread(new ThreadStart(() =>
{
{
Thread.Sleep(1000);
};
})).Start();
like Marc already said the Dispatcher.BeginInvoke() pushes all the code int the Action to the UI Thread so the code gets executed there if you want your UI to stay responsive, do the Calculations before you call Dispatcher.Begin Invoke and then set your UI Controls in the BeginInvoke.
new Thread(new ThreadStart(() =>
{
int result = MyHeavyCalculation();
Dispatcher.BeginInvoke(new Action(() =>
{
label1.Text = result.ToString();
}));
})).Start();
Or have a look at async-await to execute methods asynchron and dont bother with UI threadsynchronization yourself. Simple Example
I am developping a WPF application.
I have a couple of timers that work asynchronously and they are created with System.Threading.Timer objects.
new System.Threading.Timer(
new System.Threading.TimerCallback(Timer_Function),
null,
timing,
timing
);
Timer_Function()
{
/*code that runs asynchronously */
}
In order to update the controls that are in WPF view I use delegate methods called by Dispatcher.Invoke otherwise the compiler would raise InvalidOperationException (The calling thread cannot access this object because a different thread owns it.)
My problem is that the delegate method do not run asynchronously and i have to do a lot of work in it so the application stops.
What can i do to run delegate method asynchronously?
What you need to do is separate out your business logic for determining what you should display, from the code that displays the results of those calculations to the UI. The business logic, the non-UI code, should be run in a non-UI thread and compute some result. That result should then be given to a method that will marshal to the UI thread and then display those results.
If you need your program to continue executing when the Timer_Function() code is run you could use a Task.Run to perform the work on a worker thread.
As always with parallel execution you need to beware of synchronization issues. Make sure you don't need the results before the work is processed and dispathed. Using the dispatcher as you mentioned might be enough, just make sure you think it through.
Something like:
Timer_Function()
{
Task.Run(() =>
{
/* do your work here */
});
}
Sorry if I misunderstood your issue
For asynchronous tasks, use this -
Task.Factory.StartNew(() =>
{
// Code which needs to run asynchronously
}.ContinueWith(task =>
{
Application.Current.Dispatcher.Invoke(new Action(() =>
{
// Code in which you are updating UI
});
}
I have recently started programming in WPF and bumped into the following problem. I don't understand how to use the Dispatcher.Invoke() method. I have experience in threading and I have made a few simple Windows Forms programs where I just used the
Control.CheckForIllegalCrossThreadCalls = false;
Yes I know that is pretty lame but these were simple monitoring applications.
The fact is now I am making a WPF application which retrieves data in the background, I start off a new thread to make the call to retrieve the data (from a webserver), now I want to display it on my WPF form. The thing is, I cannot set any control from this thread. Not even a label or anything. How can this be resolved?
Answer comments:
#Jalfp:
So I use this Dispatcher method in the 'new tread' when I get the data? Or should I make a background worker retrieve the data, put it into a field and start a new thread that waits till this field is filled and call the dispatcher to show the retrieved data into the controls?
The first thing is to understand that, the Dispatcher is not designed to run long blocking operation (such as retrieving data from a WebServer...). You can use the Dispatcher when you want to run an operation that will be executed on the UI thread (such as updating the value of a progress bar).
What you can do is to retrieve your data in a background worker and use the ReportProgress method to propagate changes in the UI thread.
If you really need to use the Dispatcher directly, it's pretty simple:
Application.Current.Dispatcher.BeginInvoke(
DispatcherPriority.Background,
new Action(() => this.progressBar.Value = 50));
japf has answer it correctly. Just in case if you are looking at multi-line actions, you can write as below.
Application.Current.Dispatcher.BeginInvoke(
DispatcherPriority.Background,
new Action(() => {
this.progressBar.Value = 50;
}));
Information for other users who want to know about performance:
If your code NEED to be written for high performance, you can first check if the invoke is required by using CheckAccess flag.
if(Application.Current.Dispatcher.CheckAccess())
{
this.progressBar.Value = 50;
}
else
{
Application.Current.Dispatcher.BeginInvoke(
DispatcherPriority.Background,
new Action(() => {
this.progressBar.Value = 50;
}));
}
Note that method CheckAccess() is hidden from Visual Studio 2015 so just write it without expecting intellisense to show it up. Note that CheckAccess has overhead on performance (overhead in few nanoseconds). It's only better when you want to save that microsecond required to perform the 'invoke' at any cost. Also, there is always option to create two methods (on with invoke, and other without) when calling method is sure if it's in UI Thread or not. It's only rarest of rare case when you should be looking at this aspect of dispatcher.
When a thread is executing and you want to execute the main UI thread which is blocked by current thread, then use the below:
current thread:
Dispatcher.CurrentDispatcher.Invoke(MethodName,
new object[] { parameter1, parameter2 }); // if passing 2 parameters to method.
Main UI thread:
Application.Current.Dispatcher.BeginInvoke(
DispatcherPriority.Background, new Action(() => MethodName(parameter)));
The #japf answer above is working fine and in my case I wanted to change the mouse cursor from a Spinning Wheel back to the normal Arrow once the CEF Browser finished loading the page. In case it can help someone, here is the code:
private void Browser_LoadingStateChanged(object sender, CefSharp.LoadingStateChangedEventArgs e) {
if (!e.IsLoading) {
// set the cursor back to arrow
Application.Current.Dispatcher.BeginInvoke(DispatcherPriority.Background,
new Action(() => Mouse.OverrideCursor = Cursors.Arrow));
}
}