これに代わるアプローチを提案したいと思います。
多数の 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 は応答し続けます。