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?

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.

Sign up to request clarification or add additional context in comments.

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
}

Comments

Your Answer

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.