J. Lennon
J. Lennon

Reputation: 3361

Async/Await + FromEvent method

Based on the following question: General purpose FromEvent method

How do I know which thread in my application the event will return? I can somehow specify which thread will it continue? What happens to the thread that is using this feature?

These responses appear to be obvious when I use WPF (Dispatcher/Main/UI Thread), but if I'm working with threads MTA, STA, Reactive, ThreadPool (Task/BackgroundWorker), how can I predict what will happen?

Is there any real benefit than using task.Wait() (if I do not have to worry about locking thread)?

Upvotes: 0

Views: 299

Answers (3)

Servy
Servy

Reputation: 203825

How do I know which thread in my application the event will return?

You don't. You never do with events, unless the documentation for a specific event specifies the that it will be executed from the UI thread, a thread pool thread, etc.

I can somehow specify which thread will it continue?

If you want to run code in a UI thread then marshal to the UI thread in the event handler. If you want to run code in a thread pool thread then add a new task to the thread pool inside of the handler. Both of those tasks add overhead if not needed, so it's usually best to look at the documentation of the event to see which is needed.

However, in the case of the linked question, the whole idea is that you're no longer dealing with an event and an event handler, you're dealing with a Task. So if you add a continuation to the task, the question is where will that continuation run? That is entirely specified by you. You can use the default task scheduler and have it run in the thread pool, you can pass a UI SynchronizationContext to run in the UI thread, or you can just let it run wherever the task you are continuing runs. (Meaning you have no idea what thread will be running it.)

If you're using the task with await, then it will automatically configure the continuation to run in the synchronization context you were in before you started that async operation, which may or may not be the UI thread (but likely is). If you specifically don't want that, then use .ConfigureAwait(false);.

Is there any real benefit than using task.Wait() (if I do not have to worry about locking thread)?

The reason to use an asynchronous task based approach is that you're not blocking threads, particularly thread pool threads (since you've specifically said you're not blocking a UI, which is much worse). Having a thread sitting around doing nothing is a problem, in some environments more than others (such as ASP for a highly active site). By not doing a blocking wait, you aren't consuming those resources.

Upvotes: 2

usr
usr

Reputation: 171246

Using the technique you linked to you cannot predict the thread that this runs on. It might be the thread raising the event, but that is not guaranteed (no, really! It isn't. This is a common misbelief).

So you need to force a switch to whatever thread you want to run on. For example use Task.Run to switch to the thread pool or use TaskScheduler.FromCurrentSynchronizationContext to run on the UI.

If you await the task you are guaranteed to resume in the synchronization context that was set before the await. This is probably what you want.

Upvotes: 1

Stephen Cleary
Stephen Cleary

Reputation: 457207

If you await a Task, then there is a "context" that is captured and used to resume the async method. This "context" is the current SynchronizationContext, unless it is null, in which case it's the current TaskScheduler (which these days is usually the thread pool scheduler).

If you're doing async programming, you should be using await and not Wait. Wait can cause deadlocks, as I explain on my blog.

You may also find my async/await intro helpful.

Upvotes: 2

Related Questions