[英]Do I need to worry about blocking tasks?
我需要擔心在.NET中阻塞任務多少錢? 即.NET任務調度程序如何處理線程池中的線程阻塞和超額訂閱?
例如,如果我在任務中有一些IO,我是否應該始終使用LongRunning
提示創建它? 或者任務調度程序啟發式更好地處理它? 在C ++中有一個Oversubscribe
提示可以很好地工作,但我沒有在.NET中找到任何等價物。
如果您需要性能最佳的代碼,則需要擔心它。
處理它的最好方法是使用.Net 4.5“等待”風格的I / O.
如果你沒有.Net 4.5,你將不得不使用較舊的I / O風格 (它的工作原理也一樣,但更難使用)。
這些文章中描述的非阻塞I / O是迄今為止使用多個線程進行I / O的最佳方式。
如果您不使用I / O,那么您可能仍會從這些文章中學到很多東西。
ThreadPool會檢測其中一個線程是否阻塞,並提示它將另一個線程添加到池中。 所以,如果你阻塞了很多,性能很可能不會很糟糕,因為ThreadPool會試圖讓你的CPU核心保持忙碌。
但是有許多被阻塞的線程可能是一個性能問題,因為它會增加內存消耗並導致更多的上下文切換。
此外,此行為可能會導致IO性能下降。 對於旋轉磁盤(HDD),同時訪問許多文件會導致大量搜索,這會嚴重影響性能。
LongRunning
向TPL LongRunning
信號, 不使用線程LongRunning
線程 - 它創建一個非線程池線程來滿足請求(例如new Thread(...)
)。 這不是你應該為IO做的。 您應該使用異步IO。 例如:
using(var response = (HttpWebResponse)await WebRequest.Create(url).GetResponseAsync())
return response.StatusCode == HttpStatusCode.OK;
這樣可以確保盡可能使用重疊的IO - 它使用IO線程池。
如果要將任務與舊版APM API一起使用,可以使用FromAsync:
Task<int> bytesRead = Task<int>.Factory.FromAsync(
stream.BeginRead, stream.EndRead, buffer, 0, buffer.Length, null);
await bytesRead;
如果您需要處理遺留事件異步API,可以使用TaskCompletionSource:
TaskCompletionSource<string[]> tcs = new TaskCompletionSource<string[]>();
WebClient[] webClients = new WebClient[urls.Length];
object m_lock = new object();
int count = 0;
List<string> results = new List<string>();
for (int i = 0; i < urls.Length; i++)
{
webClients[i] = new WebClient();
// Specify the callback for the DownloadStringCompleted
// event that will be raised by this WebClient instance.
webClients[i].DownloadStringCompleted += (obj, args) =>
{
// Argument validation and exception handling omitted for brevity.
// Split the string into an array of words,
// then count the number of elements that match
// the search term.
string[] words = args.Result.Split(' ');
string NAME = name.ToUpper();
int nameCount = (from word in words.AsParallel()
where word.ToUpper().Contains(NAME)
select word)
.Count();
// Associate the results with the url, and add new string to the array that
// the underlying Task object will return in its Result property.
results.Add(String.Format("{0} has {1} instances of {2}", args.UserState, nameCount, name));
// If this is the last async operation to complete,
// then set the Result property on the underlying Task.
lock (m_lock)
{
count++;
if (count == urls.Length)
{
tcs.TrySetResult(results.ToArray());
}
}
};
// Call DownloadStringAsync for each URL.
Uri address = null;
address = new Uri(urls[i]);
webClients[i].DownloadStringAsync(address, address);
} // end for
await tcs.Task;
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.