What I'm trying to do is perform a heavy task triggered by a button event on the MainWindow, but still be able to drag the window freely. I've tried both the async/await pattern and creating new threads. However, threads will be nonblocking, MainWindow still freezes. Here's the code:
uiTIN.Click += async (o, e) =>
{
var _ = await Task.Run(() => job());
};
That's the button callback and here is the func:
private int job()
{
this.Dispatcher.Invoke(() =>
{
//Other function calls here omitted
});
return 0;
}
EDIT: The workaround was to use BackgroundWorker and I have also decorated dependent UI code snippets in Dispatcher Invoke function
From Microsoft's doccumentation on Dispatcher (emphasis mine):
In WPF, a
DispatcherObject
can only be accessed by theDispatcher
it is associated with. For example, a background thread cannot update the contents of aButton
that is associated with theDispatcher
on the UI thread. In order for the background thread to access theContent
property of the Button, the background thread must delegate the work to theDispatcher
associated with the UI thread. This is accomplished by using eitherInvoke
orBeginInvoke
.Invoke
is synchronous andBeginInvoke
is asynchronous. The operation is added to the queue of theDispatcher
at the specifiedDispatcherPriority
.
So basically what you're doing is call an asynchronous method, and then forcing it to run on the UI thread, which accomplishes nothing.
In your //Other function calls here omitted
, I'm asuming that you need to access some part of the UI, if that's not the case, all you have to do is remove the Dispatcher.Invoke
from your method.
If my assumptions are right, then you must figure out a way of splitting your function, so that the part that isn't UI related run in a Background thread and only what needs to run on the UI Thread actually do.
My suggestion is to use a Background Worker
. Here's how it'd look:
uiTIN.Click += (o, e) =>
{
job();
};
... and then ...
private int job()
{
BackgroundWorker worker = new BackgroundWorker();
worker.DoWork += (s, e) =>
{
// Part of other function calls here omitted that don't need to run on the UI thread
Dispatcher.Invoke(() =>
{
// Part of other function calls here omitted that must run on the UI thread
});
};
worker.RunWorkerAsync();
return 0;
}