. Net (C #): task. Unwrap Extension Method and async Lambda

Source: Internet
Author: User

Directory

  • Basic use of task. Unwrap
  • Unwrap operations for task. Factory. startnew and task. Run
  • Use Case: async Lambda in LINQ

 

Returned directory

Basic use of task. Unwrap

This extension method is defined in the taskextensions type, and the namespace is in system. Threading. Tasks. Unwrap extracts the nested <task> or <task <t> results.

 

Like this, unwrap is not needed:

Static void main (string [] ARGs)

{

Doo ();

Task. Delay (-1). Wait ();

}

 

Static async void doo ()

{

// Run nested tasks

// Task returned by the task <string>

// The result type after the first await is task <string>

VaR result = await task. Run <task <string> () =>

{

VaR task = task. Run <string> () =>

{

Task. delay( 1000). Wait ();

Return "mgen ";

});

Return task;

});

 

// The string is returned only after the second await.

Console. writeline (await result );

}

 

After unwrap is used, the results can be extracted directly from nested tasks:

 

Static async void doo ()

{

// Run nested tasks

// Task returned by the task <string>

// The await post-type is task <string>, and the result type after unwrap is string.

VaR result = await task. Run <task <string> () =>

{

VaR task = task. Run <string> () =>

{

Task. delay( 1000). Wait ();

Return "mgen ";

});

Return task;

}). Unwrap ();

 

// Await is not required. The result is a string.

Console. writeline (result );

}

 

 

Returned directory

Unwrap operations for task. Factory. startnew and task. Run

To put it simply, task. factory. startnew and task. one of the differences between run is task. run automatically executes the unwrap operation, but the task. factory. startnew No, task. run is a task. factory. startnew is more user-friendly, while task. factory. startnew indicates the original execution. (For more differences, we recommend a very powerful article by pfx team: task. Run vs task. Factory. startnew ).

 

Verify by code:

VaR task1 = task. Factory. startnew (async () => "mgen ");

VaR task2 = task. Run (async () => "mgen ");

 

Console. writeline (task1.gettype ());

Console. writeline (task2.gettype ());

 

Output:

System. Threading. Tasks. Task '1 [system. Threading. Tasks. task' 1 [system. String]

System. Threading. Tasks. unwrappromise '1 [system. String]

 

We can see that

When task. Factory. startnew is used, the original task <string> is returned. However, task. run directly returns the result of async lambda, And the unwrap operation in the middle is automatically performed.

 

 

Returned directory

Use Case: async Lambda in LINQ

The article tells us that it may be rare for readers to think about the above situation? No, any use of async Lambda may encounter the above situation. For example, if a winrt project is recently established and some data is converted using LINQ, however, many winrt APIs only run asynchronously, and such problems may occur. the following example:

 

Let's perform a simple, but non-trivial LINQ Select Operation to convert a bunch of int to string, but the conversion process is asynchronous. Let's look at the Code:

Static void main (string [] ARGs)

{

Doo ();

Task. Delay (-1). Wait ();

}

 

Static void doo ()

{

// Int data

VaR ints = enumerable. Range (1, 10 );

// Convert and output the result

Foreach (var str in ints. Select (async I => await int2stringasync (I )))

Console. writeline (STR );

}

 

// Convert int to string Asynchronously

Static async task <string> int2stringasync (int I)

{

Return await task. Run <string> () => I. tostring ());

}

 

Is the above Code correct? Many people think it is okay. The select method calls the asynchronous conversion method through an async Lambda and waits for the result asynchronously using await. Then async Lambda returns the string, and the STR type is also the string type, the final output is a string.

 

But in fact, after the program runs, it will output:

System. Threading. Tasks. Task '1 [system. String]

System. Threading. Tasks. Task '1 [system. String]

System. Threading. Tasks. Task '1 [system. String]

System. Threading. Tasks. Task '1 [system. String]

System. Threading. Tasks. Task '1 [system. String]

System. Threading. Tasks. Task '1 [system. String]

System. Threading. Tasks. Task '1 [system. String]

System. Threading. Tasks. Task '1 [system. String]

System. Threading. Tasks. Task '1 [system. String]

System. Threading. Tasks. Task '1 [system. String]

 

The STR variable is not a string, but a task <string>. The above inference is wrong (marked in the yellow text above) "async Lambda returns string". The async Lambda result is not await. The above await is only an asynchronous wait for the int2stringasync method, async Lambda still Returns Task <string>, so select Returns Task <string> of some columns.

 

The simplest solution is to add await to the processing result as follows:

// The STR type is actually: Task <string>

Console. writeline (STR );

 

This is the best method (if so), because with this await, the entire conversion process is actually asynchronous!

 

Of course, if you want to directly return the result string in the linq select statement instead of the task <string>:

There is also a solution that does not use async Lambda and there is no nested task problem. The result attribute of the Asynchronous Method is returned directly in the SELECT statement:

// Int data

VaR ints = enumerable. Range (1, 10 );

// Select calls the Asynchronous Method

Ienumerable <string> STRs = ints. Select (I => int2stringasync (I). Result );

 

If you must use async lambda, you must unwrap nested tasks. (Of course, this is more about the technology itself. In actual work, it is not necessary to be so arrogant .)

Based on the knowledge mentioned above, an unwrap is required to use task. Factory. startnew, and the result of the task <t> is returned as the final return value of the select method. Code:

// Int data

VaR ints = enumerable. Range (1, 10 );

// Select calls the Asynchronous Method

Ienumerable <string> STRs = ints. Select (I =>

Task. Factory. startnew (async () => await int2stringasync (I). Unwrap (). Result );

 

In task. Run, unwrap is not required:

Ienumerable <string> STRs = ints. Select (I =>

Task. Run (async () => await int2stringasync (I). Result );

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.