1

I am trying to understand async programming, and I had a question. It is regarding the following functions below.

public async void TestAsyncCall() {
Task<string> TaskResult1 = DoSomethingAsync();
string Result2 = DoSomething();
string Result1 = await TaskResult1; 
}
public string DoSomething() {
return "synch";
}
public async Task<string> DoSomethingAsync() {
await Task.Delay(10000);
return "asynch";
}

In the function call TestAsyncCall(), would one thread be used to execute DoSomethingAsync(), and another thread to execute DoSomething()?

Then when await is encountered, it would wait for DoSomethingAsync() to complete and release that thread (while also not blocking the original thread)?

Or will this not warrant any new threads being created? In that case will the DoSomethingAsync call be relevant only if it were to deal with some external resource?

asked Jun 25, 2017 at 17:34
6
  • 2
    Start reading up here msdn.microsoft.com/en-us/magazine/jj991977.aspx Commented Jun 25, 2017 at 18:34
  • Async programming is not always about extra threads. You can await timers, the disk or the net, too. None of these block the main thread while the code is technically single threaded. That's why the Task abstraction of an async activity is more general than just threads. You don't even often need to think what the actual implementation is. Commented Jun 25, 2017 at 22:16
  • 2
    Also start reading up here msdn.microsoft.com/en-us/magazine/dn802603.aspx Commented Jun 26, 2017 at 14:11
  • You have async void. This is not good. It's a giant red flag. If you have async void you should immediatley know you've got a problem. Methods marked as async should always return a Task or Task<T> (unless you've implemented your own special type, see the documentation). Commented Jun 26, 2017 at 14:13
  • If you have async void you should immediately know you've got a problem is not necessarily true (although not wrong), although it's a poor strategy/design, async void is inevitable for event handlers. Commented Jun 26, 2017 at 14:16

2 Answers 2

2

I recommend you read my article on async ASP.NET.

Or will this not warrant any new threads being created?

This won't create any new threads. In particular, async and await by themselves won't create any new threads.

On ASP.NET, it's likely that the code after an await will run on a different thread than the code before that await. This is just exchanging one thread for another, though; no new threads are created.

In that case will the DoSomethingAsync call be relevant only if it were to deal with some external resource?

The primary use case for async is to deal with I/O, yes. This is particularly true on ASP.NET.

answered Jun 26, 2017 at 15:58

Comments

2

As @Stepehen-cleary said, "In particular, async and await by themselves won't create any new threads."

This next example is taken from the book: "C sharp in Depth" by John Skeet, chapter 15 pp.465:

class AsyncForm : Form
{
 /* The first part of listing 15.1 simply creates the UI and hooks up an event handler for
 the button in a straightforward way */
 Label label;
 Button button;
 public AsyncForm()
 {
 label = new Label { 
 Location = new Point(10, 20),
 Text = "Length" 
 };
 button = new Button {
 Location = new Point(10, 50),
 Text = "Click" 
 }; 
 button.Click += DisplayWebSiteLength;
 AutoSize = true;
 Controls.Add(label);
 Controls.Add(button);
 } 
 /* When you click on the button, the text of the book’s home page is fetched
 and the label is updated to display the HTML lenght in characters */
 async void DisplayWebSiteLength(object sender, EventArgs e)
 {
 label.Text = "Fetching...";
 using (HttpClient client = new HttpClient())
 {
 string text =
 await client.GetStringAsync("http://csharpindepth.com");
 label.Text = text.Length.ToString();
 }
 }
 /* The label is updated to display the HTML length in characters D. The
 HttpClient is also disposed appropriately, whether the operation succeeds or fails—
 something that would be all too easy to forget if you were writing similar asynchronous
 code in C# 4 */
}

With this in mind, let's take a look to your code, you have Result1 and Result2, there's no point in having one asynchronous task waiting for a synchronous task to be finished. I would use Parallelism so you can perform both methods but to return something like two sets of Data, performing LINQ queries at the same time.

Take a look to this short example about Parallelism with Async Tasks:

public class StudentDocs 
{
 //some code over here
 string sResult = ProcessDocs().Result;
 //If string sResult is not empty there was an error
 if (!sResult.Equals(string.Empty))
 throw new Exception(sResult);
 //some code over there
 ##region Methods 
 public async Task<string> ProcessDocs() 
 {
 string sResult = string.Empty;
 try
 {
 var taskStuDocs = GetStudentDocumentsAsync(item.NroCliente);
 var taskStuClasses = GetStudentSemesterClassesAsync(item.NroCliente, vencimientoParaProductos);
 //We Wait for BOTH TASKS to be accomplished...
 await Task.WhenAll(taskStuDocs, taskStuClasses);
 //Get the IList<Class>
 var docsStudent = taskStuDocs.Result;
 var docsCourses = taskStuClasses.Result;
 /*
 You can do something with this data ... here
 */
 }
 catch (Exception ex)
 {
 sResult = ex.Message;
 Loggerdb.LogInfo("ERROR:" + ex.Message);
 }
 }
 public async Task<IList<classA>> GetStudentDocumentsAsync(long studentId)
 {
 return await Task.Run(() => GetStudentDocuments(studentId)).ConfigureAwait(false);
 }
 public async Task<IList<classB>> GetStudentSemesterCoursessAsync(long studentId)
 {
 return await Task.Run(() => GetStudentSemesterCourses(studentId)).ConfigureAwait(false);
 }
 //Performs task to bring Student Documents
 public IList<ClassA> GetStudentDocuments(long studentId)
 {
 IList<ClassA> studentDocs = new List<ClassA>();
 //Let's execute a Stored Procedured map on Entity Framework
 using (ctxUniversityData oQuery = new ctxUniversityData())
 {
 //Since both TASKS are running at the same time we use AsParallel for performing parallels LINQ queries
 foreach (var item in oQuery.GetStudentGrades(Convert.ToDecimal(studentId)).AsParallel())
 {
 //These are every element of IList
 studentDocs.Add(new ClassA(
 (int)(item.studentId ?? 0),
 item.studentName,
 item.studentLastName,
 Convert.ToInt64(item.studentAge),
 item.studentProfile,
 item.studentRecord
 ));
 }
 }
 return studentDocs;
 }
 //Performs task to bring Student Courses per Semester
 public IList<ClassB> GetStudentSemesterCourses(long studentId)
 {
 IList<ClassB> studentCourses = new List<ClassB>();
 //Let's execute a Stored Procedured map on Entity Framework
 using (ctxUniversityData oQuery = new ctxUniversityData())
 {
 //Since both TASKS are running at the same time we use AsParallel for performing parallels LINQ queries
 foreach (var item in oQuery.GetStudentCourses(Convert.ToDecimal(studentId)).AsParallel())
 {
 //These are every element of IList
 studentCourses.Add(new ClassB(
 (int)(item.studentId ?? 0),
 item.studentName,
 item.studentLastName,
 item.carreerName,
 item.semesterNumber,
 Convert.ToInt64(item.Year),
 item.course ,
 item.professorName
 ));
 }
 }
 return studentCourses;
 }
 #endregion
}
answered Jun 26, 2017 at 19:48

Comments

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.