Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
CSharpNotesForProfessionals.pdf
Скачиваний:
57
Добавлен:
20.05.2023
Размер:
6.12 Mб
Скачать

public async Task MethodA()

{

await MethodB();

// Do other work

}

public async Task MethodB()

{

await MethodC();

// Do other work

}

public async Task MethodC()

{

// Or await some other async work await Task.Delay(100);

}

This will not perform any better than

public void MethodA()

{

MethodB();

// Do other work

}

public void MethodB()

{

MethodC();

// Do other work

}

public void MethodC()

{

Thread.Sleep(100);

}

The primary purpose of async/await is to allow the machine to do additional work - for example, to allow the calling thread to do other work while it's waiting for a result from some I/O operation. In this case, the calling thread is never allowed to do more work than it would have been able to do otherwise, so there's no performance gain over simply calling MethodA(), MethodB(), and MethodC() synchronously.

Section 114.6: Web.config setup to target 4.5 for correct async behaviour

The web.config system.web.httpRuntime must target 4.5 to ensure the thread will renter the request context before resuming your async method.

<httpRuntime targetFramework="4.5" />

Async and await have undefined behavior on ASP.NET prior to 4.5. Async / await will resume on an arbitrary thread that may not have the request context. Applications under load will randomly fail with null reference exceptions accessing the HttpContext after the await. Using HttpContext.Current in WebApi is dangerous because of async

Section 114.7: Simple consecutive calls

public async Task<JobResult> GetDataFromWebAsync()

GoalKicker.com – C# Notes for Professionals

588

{

var nextJob = await _database.GetNextJobAsync();

var response = await _httpClient.GetAsync(nextJob.Uri);

var pageContents = await response.Content.ReadAsStringAsync(); return await _database.SaveJobResultAsync(pageContents);

}

The main thing to note here is that while every await-ed method is called asynchronously - and for the time of that call the control is yielded back to the system - the flow inside the method is linear and does not require any special treatment due to asynchrony. If any of the methods called fail, the exception will be processed "as expected", which in this case means that the method execution will be aborted and the exception will be going up the stack.

Section 114.8: Blocking on async code can cause deadlocks

It is a bad practice to block on async calls as it can cause deadlocks in environments that have a synchronization context. The best practice is to use async/await "all the way down." For example, the following Windows Forms code causes a deadlock:

private async Task<bool> TryThis()

{

Trace.TraceInformation("Starting TryThis"); await Task.Run(() =>

{

Trace.TraceInformation("In TryThis task"); for (int i = 0; i < 100; i++)

{

// This runs successfully - the loop runs to completion

Trace.TraceInformation("For loop " + i); System.Threading.Thread.Sleep(10);

}

});

// This never happens due to the deadlock

Trace.TraceInformation("About to return"); return true;

}

// Button click event handler

private void button1_Click(object sender, EventArgs e)

{

//.Result causes this to block on the asynchronous call bool result = TryThis().Result;

//Never actually gets here

Trace.TraceInformation("Done with result");

}

Essentially, once the async call completes, it waits for the synchronization context to become available. However, the event handler "holds on" to the synchronization context while it's waiting for the TryThis() method to complete, thus causing a circular wait.

To fix this, code should be modified to

private async void button1_Click(object sender, EventArgs e)

{

bool result = await TryThis(); Trace.TraceInformation("Done with result");

}

GoalKicker.com – C# Notes for Professionals

589

Note: event handlers are the only place where async void should be used (because you can't await an async void method).

GoalKicker.com – C# Notes for Professionals

590