calling an async function from. a custom. thread in c# - c#

I'm working on some old code that runs on custom background thread. this thread uses the thread class and passes it a thread delegate i.e. an action.
_thread = new Thread(() => processData());
i need to call some newer functions that return task so do i just do
myfunc().GetAwaiter().GetResult();
or is there some other way? because since it is a custom thread, i don't think if it is really doing anything this time. how can i call async await from. the custom thread so that it is utilized properly?

If you want to continue using your custom Thread, then yes, it has to block on asynchronous code. GetAwaiter().GetResult() is probably your best bet for that.
or is there some other way?
Yes. If you can replace your custom Thread with a thread pool thread, then you can use Task.Run instead of Thread, and then you can use the more natural await instead of GetAwaiter().GetResult(). Most custom threads can be replaced by thread pool threads, but this is not always the case.

Related

Execute Task.Run on main thread

I am using monotouch/Xamarin for an iOS app.
The documentation for Task.Run states:
Queues the specified work to run on the ThreadPool and returns a task
handle for that work.
Which essentially indicates that it could run on any thread ThreadPool.
I want to do something like:
Task.Run(async () => await PerformTask());
but have it run on the main thread. Normally I would write it using BeginInvokeOnMainThread as follows:
BeginInvokeOnMainThread(async () => await PerformTask());
But I am doing this in shared code and do not want to use iOS specific calls. Is there a way for me to tell Task.Run() to invoke the action on the main thread?
If you want to run PerformTask in the current thread, instead of a thread pool thread, you simply need to not call Task.Run. Just use:
PerformTask();
and you're done. If you want to only continue executing the rest of the method when that task is done, then await it:
await PerformTask();
There is no reason to call Task.Run here for you, nor is there any reason to create a lambda that awaits the method for no particular reason (you could just call it directly if you wanted to start it from a thread pool thread).
If you want to run a task from the main thread you could use TaskSchedluer's method FromCurrentSynchronizationContext().
Task t = new Task(() =>
{
...
});
t.Start(TaskScheduler.FromCurrentSynchronizationContext());
This can be useful sometimes. However, if you want to use this technique to bypass thread checks (for example, modifying properties of form controls in a windows app), you should rethink your design. Use tasks for calculations or other non-UI operations and update the UI from the main thread.
Have a look at MainQueue.cs: https://gist.github.com/gering/0aa9750d3c7d14b856d0ed2ba98374a8
It is for Xamarin Forms applications. You have to call Init() from main thread once, but then you are able to ensure execution on main thread.

How can I queue a function to be invoked by the MainThread in C#?

I have found plenty of resources for how to invoke a function on the UI thread, but I have some logic that is only allowed to be run from the Main Thread. Is there a way to grab a dispatcher on the Main thread and invoke on it?
The "dispatcher" is a concept specific to a particular UI framework (here: WPF). There is no dispatcher you can use to target any thread. Imagine the following thread:
while (true) Console.WriteLine("x");
How are you going to invoke something on that thread? It can't be done because that thread is forever busy doing something else. It is not cooperating.
I kind of doubt that you need to invoke something on the "main thread". But I'll answer the question literally. You need to make the main thread cooperate and accept work from other threads. Maybe a queue of Action or a boolean flag that tells that thread to do something specific.
You can use a combination of signaling + data structures. Define a variable to hold details of a required function call (maybe a struct with parameters), and have your main thread periodically test if a call is required. Make sure to lock necessary objects the handle multi-threading pitfalls. You can also have a signaling object and have the initiator Monitor.Wait on it and the main thread will signal when the function is done.
Edit: The program the OP questioned about did in fact have separate UI and Main threads...
You can create new threads/tasks anytime you want using
tokenSource = new CancellationTokenSource();
token = tokenSource.Token;
Task.Factory.StartNew(() =>
{
doSomeWork();
}, token);
The token is used so you can cancel the task. If something goes wrong or the task hangs, you can cancel it. You may have already read about TPL libraries but if not, do and see if it works for what you are wanting to do.
To make my answer a little more complete I wanted to add this...I am not sure this may or may not work in your case but in normal cases you would do something like this to update or work with objects in the main thread from the worker thread.
private void doSomeWork()
{
// do work here -->
if (someObject.InvokeRequired)
{
someObject.BeginInvoke((Action)delegate() { someObject.Property = someValue; });
}
else
{
someObject.Property = someValue;
}
}

async /await for methods in wpf aplication

I have such question. For example I create dynamically custom userControl using mvvm pattern. So I've sended a command to create an userControl. So creation looks like
private async Task<bool> OnAddUserControl1(List<ALV_VM_ADWERT> control)
{
try
{
_cancellationTokenSource = new CancellationTokenSource();
var userControl = _userControlsContainer.CreateUserControl1(control);
var task1 = Task.Factory.StartNew(() =>
{
userControl.ViewModel.InOperationEvent += OnUsercontrolInOperationChanged;
userControl.ViewModel.ValueTypeChangedEvent += OnValueTypeChanged;
userControl.ViewModel.SetExpandableName += OnSetExpandableName;
}, _cancellationTokenSource.Token, TaskCreationOptions.AttachedToParent, TaskScheduler.FromCurrentSynchronizationContext());
var task2 = Task.Factory.StartNew(() => FinalCreatingStep(userControl, control[0].RAUMNAME.Trim()), _cancellationTokenSource.Token, TaskCreationOptions.AttachedToParent, TaskScheduler.FromCurrentSynchronizationContext());
await Task.WhenAll(task1, task2);
return true;
}
catch (Exception)
{
return false;
}
}
and my question is - does it make sence to create child tasks, or it is better to have code without child tasks? And if the answer is yes, then should I make all methods async? If not, what methods I should not make async?
Do those event subscriptions really need to be asynchronous? You may be trying too hard to use asynchronous code.
The user control constructor is usually the most time consuming part and must be done on the UI thread. Asynchronous operations are generally only required when some form of IO or processing is involed;
Reading Files
Writing Files
Processing large data sets
Crossing the process boundary to talk to a server or connect device
In short, an asynchronous task is probably overkill here.
Does it make sence to create child tasks, or it is better to have code without child tasks?
It is depending on your requirements. If your UI will blocked (Freeze) for long time you have to create a child task, otherwise not!
And if the answer is yes, then should I make all methods async? If not, what methods I should not make async?
Here it is also depending on your requirements and your .Net Version. If you are using .NET 4.5 the easiest way to do that with Async await. If you are using .Net 3.5 than just use Task. If .Net 2 use BackgorundWorker else use Thread class. ONLY Asynchrony methods must get the word async. Other methods you do not have to change them. In other words only the method which blocked the UI.
Your current code doesn't make any sense.
The point of async code in a UI application is responsiveness - i.e., moving long-running operations off the UI thread. As #Gusdor pointed out, most of the use cases for async are I/O-based (or event-based) operations, where you don't want to block the UI thread just to wait for some result. Another use case is when you have some CPU-bound work to do, but you don't want to tie up the UI thread; in this case, you can use Task.Run.
But in your code, you're calling StartNew with TaskScheduler.FromCurrentSynchronizationContext, which means your "child" tasks are going to execute on the UI thread. So your OnAddUserControl1 is just starting tasks which will run on the same thread and asynchronously waiting for them to complete. This is a very complex way of doing nothing.
While we're on the subject of StartNew, there are a number of other problems:
The code is passing a CancellationToken without ever observing it in the delegate.
The code is specifying AttachedToParent which is incorrect for await-compatible tasks.
As mentioned above, the code is passing a TaskScheduler which will run the delegate right back on the UI thread.
If you need to use background (thread pool) tasks, you should use Task.Run instead of Task.Factory.StartNew; I go into more detail on my blog.
So for this example, it doesn't make sense to use async or await at all.
The best way to start using async is to identify the I/O-bound (or event-driven) parts first (e.g., HTTP requests, database calls), make them async, and then work your way up the call stack.

RaiseCanExecuteChanged called while await causes deadlock

I am using WPF and DelegateCommand from PRISM and have the following problem:
I start an async operation like:
public async void ProgramDevice()
{
var result = await FirmwareLoader.DownloadFirmwareAsync();
}
Inside this method an event is fired which I registered to and should update my DelegateCommand so it can't be executed:
//UiCommand is of type DelegateCommand
Engine.IsProgrammedChanged +=
(s, e) => Dispatcher.Invoke(() => UiCommand.RaiseCanExecuteChanged());
Now I have the problem, that the RaiseCanExecuteChanged causes a deadlock (I checked and the Dispatcher.Invoke does not cause it, because when I e.g. show a MessageBox instead it works fine).
Am I doing something wrong or how can I work around this problem?
I see you've already solved your problem, but I thought I'd give a more general solution that will help you prevent such deadlocks in the future.
In your case, you could easily avoid this deadlock by using ConfigureAwait like this:
var result = await FirmwareLoader.DownloadFirmwareAsync().ConfigureAwait(false);
What this does is allows the continuation to be performed on a different thread than the original. Doing so is not always possible, since a lot of times you need the continuation to be performed on the UI thread, but for this question I don't believe that's the case. So basically, the best practice is to always use ConfigureAwait(false) unless you need to resume execution from the original thread.
This article explains in detail why these kind of deadlocks happen and how to avoid them. Another recommended read is Best Practices in Asynchronous Programming.
Found the problem:
It was not the RaiseCanExecuteChanged, but the actual CanExecute which is triggered by it. In there I had an AsyncLock which waited for the programming task to be finished, before returning the value I use to descide if UiCommand can be executed --> deadlock as the programming task triggered it...
I solved it by simple using the "sync" property (which does not use the lock and just returns the current value/stat) of the value I need.
Am I doing something wrong or how can I work around this problem?
Method Dispatcher.Invoke blocks working thread until UI thread makes all updates
UI thread uses some resources locked by working thread (through RaiseCanExecuteChanged -> CanExecute method chain in the above code) and blocks
Deadlock since worker thread waits for UI thread to finish update and UI thread waits worker thread to release locked resources
A possible way to ensure no deadlocks is to asynchronously invoke updates on UI thread using Dispatcher.BeginInvoke.
//UiCommand is of type DelegateCommand
Engine.IsProgrammedChanged +=
(s, e) => Dispatcher.BeginInvoke(() => UiCommand.RaiseCanExecuteChanged());
This way UI thread will wait for a moment when working thread releases locked resources and then will update. But there will be no deadlock.

Is there a System.Threading.SynchronizationContext.Current.PostAsync()?

I can return anything back to the UI thread like this:
// when I am on the UI thread
var _UI = System.Threading.SynchronizationContext.Current;
// then on a background thread
_UI.Post((x) => { DoSomething(); }, null);
But, if I am on that background thread for to make it asynchrnous, then calling _UI.Post() will undo my efforts and makes the UI wait for the execution of DoSomething().
Of course _UI.PostAsync() is pseudo-code. But is there a way to execute on the UI thread but in an asynchronous way? Fundamentally, I realize I am exposing my lack of knowlege and understanding. Be merciful, please. I'm just asking ;)
SynchronizationContext.Post() will not block the background thread, as it asynchronously "posts" back to the UI thread (in this case).
The UI thread will only block for the duration of the DoSomething() call - but in this case, you're saying you must run that on the UI thread, in which case, it will tie up the UI thread.
The key here is to put most of your work on the background thread, and only call .Post(...) for operations that directly set the user interface. As such, they should be very fast operations, and never (noticably) block the UI.

Categories

Resources