C#多个后台工作者访问对象

时间:2013-05-07 10:05:47

标签: c# multithreading backgroundworker

我有一个字符串列表,每1000个字符长包含大约20000个字符串。我想使用多个后台工作程序用相同位置的相同字符串的反转版本替换所有这些字符串。

到目前为止我正在做的事情:

设置后台工作人员(8人因为计算机有8个核心)

 for (int j = 0; j < 8; j++)
    {
    BackgroundWorker worker = new BackgroundWorker();
    worker.DoWork += DoWork;
    worker.RunWorkerCompleted += WorkComplete;
    worker.RunWorkerAsync();
    }

我遇到的问题是我不知道在doWork函数中放什么。

dowork函数应该像这样循环:

private void DoWork(object sender, DoWorkEventArgs e)
{
   while(list.count > 0)
   {
      reverse and add to list
   }         
}

或者doWork函数是否只进行反转,然后将反向字符串传递给WorkComplete函数?

private void DoWork(object sender, DoWorkEventArgs e)
    {
       reverse string
       r.result = reversed string 
    }

2 个答案:

答案 0 :(得分:7)

我想建议另一种方法。

您可以创建一个在其DoWork()内部而不是创建一些BackgroundWorkers,而可以使用Parallel.ForEach()来反转字符串。

这样,它将为您最佳地处理线程数。

您仍然需要使用BackgroundWorker来避免锁定UI线程。

以下是在控制台应用中运行的可编辑示例:

using System;
using System.Linq;
using System.Threading.Tasks;

namespace ConsoleApplication1
{
    class Program
    {
        static void Main()
        {
            string[] data = Enumerable.Range(10000, 100).Select(i => i.ToString()).ToArray();

            Parallel.ForEach(data, (item, state, index) => data[index] = Reverse(item));

            foreach (var s in data)
                Console.WriteLine(s);
        }

        public static string Reverse(string s)
        {
            char[] charArray = s.ToCharArray();
            Array.Reverse(charArray);
            return new string(charArray);
        }
    }
}

此外,如果您使用.Net 4.5,则可以使用新的await/async功能完全避免使用BackgroundWorker。

例如,创建一个默认的Windows窗体应用程序并将一个名为label1的标签和一个名为button1的按钮放在其上。然后将Form1.cs文件更改为:

using System;
using System.Linq;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace WindowsFormsApplication1
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
            data = Enumerable.Range(10000, 1000000).Select(i => i.ToString()).ToArray();
        }

        async void button1_Click(object sender, EventArgs e)
        {
            label1.Text = "Reversing strings...";
            await doWork();
            label1.Text = "Reversed strings.";
        }

        Task doWork()
        {
            return Task.Factory.StartNew(() => Parallel.ForEach(data, (item, state, index) => data[index] = reverse(item)));
        }

        static string reverse(string s)
        {
            char[] charArray = s.ToCharArray();
            Array.Reverse(charArray);
            return new string(charArray);
        }

        readonly string[] data;
    }
}

当您单击该按钮时,UI将在字符串反转时保持响应。

答案 1 :(得分:2)

使用BackgroundWorker对您来说至关重要吗?使用TPL非常简单:

using System.Threading.Tasks;

Parallel.For(0, strings.Length, i=> strings[i] = reversed string);

TPL将为您平衡负载(默认情况下,它使用可用的CPU核心数),这也适用于具有不同核心数量的其他计算机。