简体   繁体   English

我是否需要担心阻止任务?

[英]Do I need to worry about blocking tasks?

How much do I need to worry about blocking tasks in .NET? 我需要担心在.NET中阻塞任务多少钱? ie how does the .NET task scheduler handle blocking of threads in the thread pool and oversubscription? 即.NET任务调度程序如何处理线程池中的线程阻塞和超额订阅?

Eg if I have some IO in a task, should I always create it with the LongRunning hint? 例如,如果我在任务中有一些IO,我是否应该始终使用LongRunning提示创建它? Or does the task scheduler heuristics handle it better? 或者任务调度程序启发式更好地处理它? In C++ there is an Oversubscribe hint which works perfectly but I have not found any equivalent in .NET. 在C ++中有一个Oversubscribe提示可以很好地工作,但我没有在.NET中找到任何等价物。

You do need to worry about it if you want the most performant code. 如果您需要性能最佳的代码,则需要担心它。

The best way to handle it is to use the .Net 4.5 "await" style of I/O . 处理它的最好方法是使用.Net 4.5“等待”风格的I / O.

If you don't have .Net 4.5, you will have to use the older style of I/O (which works just as well, but is harder to use). 如果你没有.Net 4.5,你将不得不使用较旧的I / O风格 (它的工作原理也一样,但更难使用)。

The non-blocking I/O described in those articles is by far the best way to do your I/O with multiple threads. 这些文章中描述的非阻塞I / O是迄今为止使用多个线程进行I / O的最佳方式。

If you are not using I/O then you might still learn much from those articles. 如果您不使用I / O,那么您可能仍会从这些文章中学到很多东西。

The ThreadPool does detect when one of its threads blocks and it is a hint for it to add another thread to the pool. ThreadPool会检测其中一个线程是否阻塞,并提示它将另一个线程添加到池中。 So, if you block a lot, the performance most likely won't be terrible, because ThreadPool will try to keep your CPU cores busy. 所以,如果你阻塞了很多,性能很可能不会很糟糕,因为ThreadPool会试图让你的CPU核心保持忙碌。

But having many blocked threads can be a performance problem, because it increases memory consumption and can lead to more context switches. 但是有许多被阻塞的线程可能是一个性能问题,因为它会增加内存消耗并导致更多的上下文切换。

Also, this behavior may lead to decreased performance of IO. 此外,此行为可能会导致IO性能下降。 With spinning disks (HDDs), accessing many files at the same time causes lots of seeking, which can affect the performance drastically. 对于旋转磁盘(HDD),同时访问许多文件会导致大量搜索,这会严重影响性能。

LongRunning signals to the TPL not to use a threadpool thread--it creates a non-threadpool thread to fulfill the request (eg new Thread(...) ). LongRunning向TPL LongRunning信号, 使用线程LongRunning线程 - 它创建一个非线程池线程来满足请求(例如new Thread(...) )。 this is not what you should be doing for IO. 不是你应该为IO做的。 You should be using asynchronous IO. 您应该使用异步IO。 For example: 例如:

using(var response = (HttpWebResponse)await WebRequest.Create(url).GetResponseAsync())
    return response.StatusCode == HttpStatusCode.OK;

this ensures, wherever possible, overlapped IO is used--which uses the IO threadpool. 这样可以确保尽可能使用重叠的IO - 它使用IO线程池。

If you want to use a Task with a legacy APM API, you can use FromAsync: 如果要将任务与旧版APM API一起使用,可以使用FromAsync:

Task<int> bytesRead = Task<int>.Factory.FromAsync( 
    stream.BeginRead, stream.EndRead, buffer, 0, buffer.Length, null);
await bytesRead;

If you need to deal with a legacy event async API, you can use TaskCompletionSource: 如果您需要处理遗留事件异步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.

相关问题 我是否需要担心画布上的最佳绘图? - Do I need to worry about optimal drawing on canvas? 我是否需要担心foreach循环中的Process - Do I need to worry about Process in foreach loop 如果没有静态字段,我是否需要担心对象是线程安全的? - Do I need to worry about an object being thread safe if it has no static fields? x:FieldModifier =“ Private”是做什么的,我应该为此担心吗? - What does x:FieldModifier=“Private” do and should I worry about it? 当我使用以下 SqlDataAdapter 时,是否需要担心插入/更新/删除/注入攻击? - Do I have to worry about inserts/updates/deletes/injection attacks when I use the following SqlDataAdapter? 我应该担心位顺序吗? - Should I worry about bit order? 在这个c#EF场景中我是否需要担心垃圾收集? - Do I have to worry about garbage collection in this c# EF scenario? 我是否需要担心 Rx.NET FromEventPattern 会导致 memory 泄漏? - Do I have to worry about memory leaks with Rx.NET FromEventPattern? 我应该担心这个DateTime数学会失去精度吗? - Should I worry about losing precision with this DateTime math? 我应该担心我的软件被反编译吗? - Should I worry about my software being decompiled?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM