当前位置:  开发笔记 > 编程语言 > 正文

在C#中使用多线程加速循环(问题)

如何解决《在C#中使用多线程加速循环(问题)》经验,为你挑选了4个好方法。

想象一下,我有一个功能,它通过一百万个/十亿字符串并检查其中的smth.

f.ex:

foreach (String item in ListOfStrings)
{
    result.add(CalculateSmth(item));
}

它消耗了大量的时间,因为CalculateSmth是非常耗时的功能.

我想问一下:如何在这种过程中集成多线程?

f.ex:我想启动5个线程,每个线程返回一些结果,直到列表中有项目为止.

也许任何人都可以展示一些例子或文章..

忘记提到我需要它在.NET 2.0中



1> noocyte..:

Parallel扩展很酷,但这也可以通过使用如下的线程池完成:

using System.Collections.Generic;
using System.Threading;

namespace noocyte.Threading
{
    class CalcState
    {
        public CalcState(ManualResetEvent reset, string input) {
            Reset = reset;
            Input = input;
        }
        public ManualResetEvent Reset { get; private set; }
        public string Input { get; set; }
    }

    class CalculateMT
    {
        List result = new List();
        List events = new List();

        private void Calc() {
            List aList = new List();
            aList.Add("test");

            foreach (var item in aList)
            {
                CalcState cs = new CalcState(new ManualResetEvent(false), item);
                events.Add(cs.Reset);
                ThreadPool.QueueUserWorkItem(new WaitCallback(Calculate), cs);
            }
            WaitHandle.WaitAll(events.ToArray());
        }

        private void Calculate(object s)
        {
            CalcState cs = s as CalcState;
            cs.Reset.Set();
            result.Add(cs.Input);
        }
    }
}



2> Tobi..:

您可以尝试并行扩展(.NET 4.0的一部分)

这些允许你写如下:

Parallel.Foreach (ListOfStrings, (item) => 
    result.add(CalculateSmth(item));
);

当然result.add需要是线程安全的.



3> slim..:

请注意,并发性并不能为您提供更多资源.你需要建立什么减慢CalculateSmth.

例如,如果它受CPU限制(并且您在单个核心上),则无论是顺序执行还是并行执行,都会将相同数量的CPU标记输入到代码中.此外,您还可以从管理线程中获得一些开销.相同的参数适用于其他约束(例如I/O)

如果CalculateSmth在执行期间保留资源,则可以在此处获得性能提升,这可以由另一个实例使用.这并不罕见.例如,如果任务涉及IO后跟一些CPU内容,则进程1可能正在执行CPU内容,而进程2正在执行IO.正如垫子所指出的那样,如果您拥有基础设施,那么生产者 - 消费者单位链就可以实现这一目标.



4> Hallgrim..:

您需要并行拆分要执行的工作.以下是如何将工作分成两部分的示例:

List work = (some list with lots of strings)

// Split the work in two
List odd = new List();
List even = new List();
for (int i = 0; i < work.Count; i++)
{
    if (i % 2 == 0)
    {
        even.Add(work[i]);
    }
    else
    {
        odd.Add(work[i]);
    }
}

// Set up to worker delegates
List oddResult = new List();
Action oddWork = delegate { foreach (string item in odd) oddResult.Add(CalculateSmth(item)); };

List evenResult = new List();
Action evenWork = delegate { foreach (string item in even) evenResult.Add(CalculateSmth(item)); };

// Run two delegates asynchronously
IAsyncResult evenHandle = evenWork.BeginInvoke(null, null);
IAsyncResult oddHandle = oddWork.BeginInvoke(null, null);

// Wait for both to finish
evenWork.EndInvoke(evenHandle);
oddWork.EndInvoke(oddHandle);

// Merge the results from the two jobs
List allResults = new List();
allResults.AddRange(oddResult);
allResults.AddRange(evenResult);

return allResults;

推荐阅读
手机用户2502851955
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有