簡體   English   中英

我是否需要擔心阻止任務?

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM