Answered by:
Can anyone explain this method TaskEx.Yield ?

Question
-
Can anyone give an example?
// // Summary: // Creates an awaitable that asynchronously yields back to the current context // when awaited. // // Returns: // A context that, when awaited, will asynchronously transition back into the // current context. If SynchronizationContext.Current is non-null, that is // treated as the current context. Otherwise, TaskScheduler.Current is treated // as the current context. public static YieldAwaitable Yield();
Tuesday, December 7, 2010 10:56 AM
Answers
-
Hi iron9light-
Conceptually, Yield enables you to temporarily leave the current async method to allow other things to be done on the underlying thread. Technically, Yield works by posting the rest of the method back to the "current context", where the current context is defined to be the current SynchronizationContext if there is one, or else the current TaskScheduler (which if you're not inside of a task defaults to TaskScheduler.Default).
The most common usage of Yield would be in places where you may have previously wanted to use something like Application.DoEvents. Let's say you were writing a UI button click handler:
public void button1_Click(...)
{
foreach(var item in data)
{
var result = Process(item);
listBox1.Items.Add(result);
}
}If the data list is small, this may be fine to do on the UI thread, but if data has any chance of being large, this foreach loop could end up blocking the UI thread for an unacceptable period of time. You can thus "Yield" out of it to allow other work to be done on the UI thread, posting back the rest of the functions processing to be done after other messages waiting to be processed:
public async void button1_Click(...)
{
int counter = 0;
foreach(var item in data)
{
var result = Process(item);
listBox1.Items.Add(result);
if ((++counter % 10) == 0) await Task.Yield();
}
}I mention this is simlar to DoEvents, but it has an important difference. DoEvents installs a new message loop, whereas Yield yields back to the existing one.
Task.Yield may also be used in server scenarios. Let's say you had a long-running function to run on the ThreadPool. You might not want to tie up a ThreadPool thread for the duration of your functions execution, thereby potentially starving other work items in the pool and/or forcing the pool to introduce more threads. You could thus Yield within your function, which will cause the rest of your function's execution to be queued as a new work item.
I hope that helps.
- Proposed as answer by Stephen Toub - MSFTMicrosoft employee, Moderator Tuesday, December 7, 2010 5:53 PM
- Marked as answer by Stephen Toub - MSFTMicrosoft employee, Moderator Monday, December 13, 2010 4:51 PM
Tuesday, December 7, 2010 5:53 PMModerator
All replies
-
Hi iron9light-
Conceptually, Yield enables you to temporarily leave the current async method to allow other things to be done on the underlying thread. Technically, Yield works by posting the rest of the method back to the "current context", where the current context is defined to be the current SynchronizationContext if there is one, or else the current TaskScheduler (which if you're not inside of a task defaults to TaskScheduler.Default).
The most common usage of Yield would be in places where you may have previously wanted to use something like Application.DoEvents. Let's say you were writing a UI button click handler:
public void button1_Click(...)
{
foreach(var item in data)
{
var result = Process(item);
listBox1.Items.Add(result);
}
}If the data list is small, this may be fine to do on the UI thread, but if data has any chance of being large, this foreach loop could end up blocking the UI thread for an unacceptable period of time. You can thus "Yield" out of it to allow other work to be done on the UI thread, posting back the rest of the functions processing to be done after other messages waiting to be processed:
public async void button1_Click(...)
{
int counter = 0;
foreach(var item in data)
{
var result = Process(item);
listBox1.Items.Add(result);
if ((++counter % 10) == 0) await Task.Yield();
}
}I mention this is simlar to DoEvents, but it has an important difference. DoEvents installs a new message loop, whereas Yield yields back to the existing one.
Task.Yield may also be used in server scenarios. Let's say you had a long-running function to run on the ThreadPool. You might not want to tie up a ThreadPool thread for the duration of your functions execution, thereby potentially starving other work items in the pool and/or forcing the pool to introduce more threads. You could thus Yield within your function, which will cause the rest of your function's execution to be queued as a new work item.
I hope that helps.
- Proposed as answer by Stephen Toub - MSFTMicrosoft employee, Moderator Tuesday, December 7, 2010 5:53 PM
- Marked as answer by Stephen Toub - MSFTMicrosoft employee, Moderator Monday, December 13, 2010 4:51 PM
Tuesday, December 7, 2010 5:53 PMModerator -
Dont know if it fits here, but I try ;)
Playing around with CTP2, I thought of creating a "block-reader" - bc it might be helpfull, but basically because it seems as a nice exercise.
Say I would like to achieve something like:
Private sub foo Dim br As New BlockReader(1024) ' passing the blocksize I like to use For each block as Byte() in br.Blocks ' do something Next end sub
Of course I want it asynchronous. To get it iteratable, Blocks must be an Iterator Property. But how do I get an non blocking read (with the new async features) inside that property? I can't say that Block is an Async property, bc Async is (currently) an extension method and therefore can not be applied to properties. But if it's not async, I cant use await.My initial idea was something like
yield await or await yield and Task(Of byte()).
Having watched the videos about the "technical" background, I understand that this might not make much sense anyway, bc yield and await are more or less "identical". So I assume that I am on the wrong track anyway. But what's the right path? Is Taskex.Yield something that leads into the right direction? Or ist it just some problem NOW, because in the next VS release async could be applied to properties?
Thursday, July 21, 2011 9:23 AM -
Hello, Picoflop, and welcome to the MSDN forums!
Generally, it is best to start a new thread when asking a different question; if your question is related to a previous question, you may include a link to the previous question in your question. This helps out future searchers.
It sounds like what you want is IAsyncEnumerable (actually part of Rx). TaskEx.Yield is conceptually closer to a "thread yield" than an "enumerable yield".
-Steve
Programming blog: http://nitoprograms.blogspot.com/
Including my TCP/IP .NET Sockets FAQ
and How to Implement IDisposable and Finalizers: 3 Easy Rules
Microsoft Certified Professional Developer
How to get to Heaven according to the BibleFriday, July 22, 2011 12:29 AM -
Thanks for your answer Stephen.
I guess I'd prefer to stay within the Async CTP and FW only and not use the RX extensions ;) I'll create a new thread when I have some code to explain more clearly what I want to achieve and to ask IF it could be done (without rx).
Regarding taskex.yield -> If I understand Stephen correctly, it's a "kind of" DoEvents. Why is it named "yield" then and not something like "ContinueEvents" - which would fit better (IMHO, but english is not my native language, so please be patient) what Stephen described?
Friday, July 22, 2011 3:23 PM -
Regarding taskex.yield -> If I understand Stephen correctly, it's a "kind of" DoEvents. Why is it named "yield" then and not something like "ContinueEvents" - which would fit better (IMHO, but english is not my native language, so please be patient) what Stephen described?
What Stephen meant is that Yield is more of a "pause" or "resume later" - i.e., you are yielding the execution of your method. This use of the "Yield" term is consistent with other uses, such as Thread.Yield (which yields the thread of execution).As far as DoEvents goes, Yield does serve a similar purpose, but DoEvents has a strong negative vibe around it. Do a search for "DoEvents is evil" and you'll see what I mean; the problem is that DoEvents starts a nested message loop. (WPF also supports nested message loops but it's much harder to do - so you have to really try to do things wrong). Yield does not use nested message loops; it causes the async function to yield back to its caller and then resume later.
Even if DoEvents didn't have a negative vibe, I would think Yield describes the meaning better than ContinueEvents (which would imply that events were suspended at some point in the past). IMO. :)
-Steve
Programming blog: http://nitoprograms.blogspot.com/
Including my TCP/IP .NET Sockets FAQ
and How to Implement IDisposable and Finalizers: 3 Easy Rules
Microsoft Certified Professional Developer
How to get to Heaven according to the Bible- Proposed as answer by Stephen Toub - MSFTMicrosoft employee, Moderator Friday, July 22, 2011 5:14 PM
Friday, July 22, 2011 3:51 PM -
There is another vital reason I ran into for using Yield before a long-running function (or even an outright kernel block). When a Task (A) marks a Task (B) as completed, there's a chance that Task (C) awaiting on Task (B) will be run directly inline, deeper into the callstack. If Task (C) then blocks, Task (A) will never return from the call to Task.SetResult(). When using async synchronization primitives to protect thread-blocking resources, you can end up with the most curiously godawful deadlocks unless you Yield first.Wednesday, September 5, 2012 6:26 PM