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

これに代わるアプローチを提案したいと思います。

多数の BackgroundWorker を作成するのではなく、1 つだけ作成し、その DoWork() 内Parallel.ForEach()で文字列を逆にするために使用できます。

そうすれば、スレッド数が最適に処理されます。

UI スレッドのロックを回避するには、BackgroundWorker を使用する必要があります。

コンソール アプリで実行されるコンパイル可能な例を次に示します。

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 フォーム アプリケーションを作成し、その上に Label という名前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 は応答し続けます。

于 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 に答える