Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/314.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
具有动态延迟的C#任务_C#_Parallel Processing_Task_Async Await - Fatal编程技术网

具有动态延迟的C#任务

具有动态延迟的C#任务,c#,parallel-processing,task,async-await,C#,Parallel Processing,Task,Async Await,我有一个函数,需要一次处理项目3,如果所花费的总时间小于x秒,线程应该在继续之前休眠剩余的秒 因此,我正在做以下工作: private void ProcessItems() { for (int i = 0, n = items.Count; i < n; i++) { Stopwatch stopwatch = new Stopwatch(); stopwatch.Start();

我有一个函数,需要一次处理项目3,如果所花费的总时间小于x秒,线程应该在继续之前休眠剩余的秒

因此,我正在做以下工作:

    private void ProcessItems()
    {
        for (int i = 0, n = items.Count; i < n; i++)
        {
            Stopwatch stopwatch = new Stopwatch();
            stopwatch.Start();

            batch.Add(items[i]);

            if (batch.Count == 3 || i >= items.Count - 3)
            {
                List<Task> tasks = new List<Task>(3);

                foreach (Item item in batch)
                    tasks.Add(Task.Factory.StartNew(() => ProcessItem(item)));

                Task.WaitAll(tasks.ToArray());

                batch.Clear();
            }

            stopwatch.Stop();

            int elapsed = (int)stopwatch.ElapsedMilliseconds;
            int delay = (3000) - elapsed;

            if (delay > 0)
                Thread.Sleep(delay);
        }
    }
private void ProcessItems()
{
对于(int i=0,n=items.Count;i=items.Count-3)
{
列表任务=新列表(3);
foreach(批量项目)
tasks.Add(Task.Factory.StartNew(()=>ProcessItem(item));
Task.WaitAll(tasks.ToArray());
batch.Clear();
}
秒表;
运行时间=(int)stopwatch.ElapsedMilliseconds;
整数延迟=(3000)-已过;
如果(延迟>0)
睡眠(延迟);
}
}
ProcessItem函数发出webrequest并处理响应(回调)。这是一个花费少量时间的函数

但是,如果我正确理解任务,一个线程可以有多个任务。因此,如果我休眠线程,其他任务可能会受到影响

是否有更有效的方法来实现上述目标,并且可以在并行中使用任务。Foreach?

使用

Task.Delay 
反而

    static async Task DoSomeProcess()
    {
        await Task.Delay(3000);
    }
你说得对,线程。睡眠会阻止其他任务


是的,您可以将异步/等待模式与并行模式配对。

任务在自动管理的线程上运行。阻塞线程本质上没有什么错误。只是有点浪费

下面是我将如何非常干净地实现这一点:

MyItem[] items = ...;
foreach(MyItem[] itemsChunk in items.AsChunked(3)) {
 Parallel.ForEach(itemsChunk, item => Process(item));
 //here you can insert a delay
}

这不会浪费一个线程,而且非常简单
Parallel.ForEach
也使用当前线程处理工作项,因此它不会处于空闲状态。您还可以添加延迟逻辑。实现是留给读者的一个练习。。。此函数用于将列表拆分为给定大小的块(3)。这样一个助手函数的好处是它将批处理逻辑从重要部分中分离出来。

您的
ProcessItems
方法可以很容易地转换为异步版本
ProcessItemsAsync
(我没有验证“批处理”逻辑):


这本身就是一个阻塞调用,可能会扼杀我们刚刚获得的
async
的优势。你能否在你的应用程序中完全消除这样的块,很大程度上取决于应用程序的其余工作流程。

是的。如果您不想为此烧掉线程,请使用
wait Task.Delay
。不过,这会迫使您使用整个异步模型。您必须将所有呼叫者也更改为使用任务。如果线程很少,那么从性能的角度来看,选择哪个模型并不重要,因为线程的开销是恒定的。与异步相比,它不会使在其上运行的东西变慢或变快。如果您不需要异步,我建议您不要使用它,因为它会使事情复杂化。Wait Task.Delay如何适合您的示例?您可以在标记的位置插入
Wait Task.Delay(3000)
,标记方法
async
,将返回类型更改为
Task
,现在必须更改所有调用者以等待返回的任务。我认为您应该研究一下异步是如何工作的,然后决定是否需要它。可能吧:不是。您是否关心某个特定问题?因此等待任务。延迟(3000)返回一个等待3000的空任务,然后?@Ivan MarkDebono否,
Task.Delay()
返回一个等待给定时间的
Task
wait Task.Delay()
异步等待该时间。是否有完整源代码工作的最终解决方案?
private async Task ProcessItemsAsync()
{
    for (int i = 0, n = items.Count; i < n; i++)
    {
        Stopwatch stopwatch = new Stopwatch();
        stopwatch.Start();

        batch.Add(items[i]);

        if (batch.Count == 3 || i >= items.Count - 3)
        {
            List<Task> tasks = new List<Task>(3);

            foreach (Item item in batch)
                tasks.Add(Task.Run(() => ProcessItem(item)));

            await Task.WhenAll(tasks.ToArray());

            batch.Clear();
        }

        stopwatch.Stop();

        int elapsed = (int)stopwatch.ElapsedMilliseconds;
        int delay = (3000) - elapsed;

        if (delay > 0)
            await Task.Delay(delay);
    }
}
ProcessItemsAsync().Wait();