[concurrency]基本async, await非同步範例(framework 4.5才有)以及用同步的方式呼叫非同步function的方法

  • 602
  • 0
  • 2015-11-02

摘要:[asp.net]簡易async, await非同步範例(framework 4.5才有)

以下來自網路的文章的片段翻譯: 實際做事的function不要加上任何非同步的修飾文字(例如:async, await, task.run,task.delay.....)

而是把這些修飾的文字使用在呼叫這個function的caller端,作者建議如果是asp.net程式,要盡量少用非同步的寫法
避免造成伺服器負擔
 

//簡易的async, await範例
protected async void btnSampleAsyncCallNonAync_Click(object sender, EventArgs e)
{
	long longResult = 0;
	longResult = await Task.Run(() => GetSumSync());
	Page.ClientScript.RegisterStartupScript(this.GetType(), "", "alert('sum=" + longResult.ToString() + "');", true);
}

//正統implement function不加入任何的threading機制
private long GetSumSync()
{
	long longSum = 0;
	for (long i = 0; i < 100000; i++)
	{
		longSum += i;
	}
	return longSum;
}

如果很不幸的,你需要呼叫網路上提供的function,而且這個function只有提供非同步版本的,該怎麼執行呢?

非同步的執行此function的範例:


//不見得每個人都知道implement function要盡量避免用threading,而是要在call端才去決定是否用threading
//如果碰到了網路上提供的function是非同步的話怎麼辦呢
//如何非同步的呼叫網路上提供的 非同步async implement function
protected async void btnSampleAsyncCallAsync_Click(object sender, EventArgs e)
{
	long longResult = 0;
	longResult = await GetSumAsync();
	Page.ClientScript.RegisterStartupScript(this.GetType(), "", "alert('sum=" + longResult.ToString() + "');", true);
}

//此implement function加入的threading機制,雖然不應該,但是這是網路上提供的,也只能用了
private async Task GetSumAsync()
{
	long longSum = 0;
	await Task.Run(() =>
	{
		for (long i = 0; i < 100000; i++)
		{
			longSum += i;
		}
	});

	return longSum;
}

同樣的網路上提供的非同步的function(對方無提供同步版本的function),如果你希望用同步的方式去執行,該怎麼做呢?


//以同步的方式去呼叫網路上提供的非同步方法,按照msdn的解釋
//該function將會強制被改回同步執行
protected void btnSampleSyncCallAsync_Click(object sender, EventArgs e)
{
	//long longResult = 0;
	//硬要改成同步執行的話,回傳的型態不是long, 而是Task
	//根據Stephen的說法,也是要極力避免,因為會造成Deadlock
	//http://blog.stephencleary.com/2012/07/dont-block-on-async-code.html
	//根據msdn的說法,也是要極力避免同步的方式去呼叫非同步的方式(文長未細看)
	//http://blogs.msdn.com/b/pfxteam/archive/2012/04/13/10293638.aspx
	//但是在不可避免的情況下,msdn建議可以利用Task.Run去做到這點
	Task t = Task.Run(() => GetSumAsync());
	//結果要用Task.Result去解開
        //如果回傳value是單純的Task,要加上
        //Task.WaitAll(t);
	Page.ClientScript.RegisterStartupScript(this.GetType(), "", "alert('sum=" + t.Result.ToString() + "');", true);
}

//GetSumAsync()跟上一個例子一樣,在此就不重複附上

 

範例程式下載(研究GitHub程式碼線上控管中,之後補上):

專案ConcurrencyWebForm的BasicSampleAsyncAwait.aspx

參考文章:

Task.Run Etiquette Examples: Don't Use Task.Run in the Implementation

http://blog.stephencleary.com/2013/11/taskrun-etiquette-examples-dont-use.html

Should I expose synchronous wrappers for asynchronous methods?

http://blogs.msdn.com/b/pfxteam/archive/2012/04/13/10293638.aspx