1

我有一个字符串列表,每 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 
    }
4

2 回答 2

7

我只是想提出一种替代方法。

您可以只创建一个并在其 DoWork() 中Parallel.ForEach()用于反转字符串,而不是创建许多 BackgroundWorker。

这样,它将为您优化处理线程数。

您仍然需要使用 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 窗体应用程序并在其上放置一个名为 Labellabel1和一个名为 的按钮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 将在字符串反转时保持响应。

于 2013-05-07T10:24:06.643 回答
2

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

using System.Threading.Tasks;

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

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

于 2013-05-07T10:21:40.517 回答