標籤:
本文轉載自 http://www.cnblogs.com/icyJ/p/Parallel_TaskFactory.html
很厲害的文章
Barrier _bar;int _maxLength = 20, _maxChannel = 2;//同時最多2條通道,每條通道最多20個資料bool _isCancel = false;private void btnWrite_Click(object sender, EventArgs e){ var tmpEmails = _emails.Where(x => !x.Value).Select(x => x.Key).ToList(); var state = 0; _isCancel = false; SetControlEnable(false); lblProgress.Text = "* 已完成 0%"; var channels = (tmpEmails.Count / _maxLength) + ((tmpEmails.Count % _maxLength > 0) ? 1 : 0);//總共多少條通道 var times = (channels / _maxChannel) + ((channels % _maxChannel > 0) ? 1 : 0);//單伺服器分多次 new Action(() => { for (int j = 0; j < times; j++) { if (_isCancel) { MessageBox.Show("任務取消!"); break; } var currChannel = Math.Min(_maxChannel, (channels - j * _maxChannel));//兩者取其小的 _bar = new Barrier(currChannel);//根據次數設定柵欄 var tasks = new Action[currChannel]; for (int i = 0; i < currChannel; i++) { var subData = tmpEmails.Skip((i + j * _maxChannel) * _maxLength).Take(_maxLength).ToList(); tasks[i] = () => { if (_isCancel) return; var resMsg = 0; Connect2WCF.RunSync(sc => resMsg = sc.UpdateMailState(subData, state)); if (resMsg == -1) MessageBox.Show("儲存失敗了?詳情可以查資料庫日誌表"); else if (resMsg == 0) subData.ForEach(one => _emails[one] = true);//標記已經完成的。 new Action(() => txtEmails.Text = string.Join("\r\n", _emails.Where(x => !x.Value).Select(x => x.Key))).InvokeRun(this); _bar.SignalAndWait(); }; } Parallel.Invoke(tasks); new Action(() => lblProgress.Text = "* 已完成 " + ((100 * (j + 1) / times)) + "%").InvokeRun(this); } new Action(() => SetControlEnable(true)).InvokeRun(this); }).RunThread();}
CancellationTokenSource cts = new CancellationTokenSource();int maxLength = 20, maxChannel = 2;//同時最多2條通道,每條通道最多20個資料private void btnWrite_Click(object sender, EventArgs e){ cts = new CancellationTokenSource(); var tmpEmails = _emails.Where(x => !x.Value).Select(x => x.Key).ToList(); var state = 0; SetControlEnable(false); lblProgress.Text = "* 已完成 0%"; var channels = (tmpEmails.Count / maxLength) + ((tmpEmails.Count % maxLength > 0) ? 1 : 0);//總共多少條通道 var times = (channels / maxChannel) + ((channels % maxChannel > 0) ? 1 : 0);//單伺服器分多次 Action<List<string>, CancellationToken> doSave = (data, ct) => { if (ct.IsCancellationRequested) return; var msg = 0; Connect2WCF.RunSync(sc => msg = sc.UpdateMailState(data, state)); if (msg == -1) MessageBox.Show("儲存失敗了?詳情可以查資料庫日誌表"); else if (msg == 0) data.ForEach(one => _emails[one] = true);//標記已經完成的。 new Action(() => txtEmails.Text = string.Join("\r\n", _emails.Where(x => !x.Value).Select(x => x.Key))).InvokeRun(this); }; for (int j = 0; j < times; j++) { int k = j; if (cts.Token.IsCancellationRequested) { MessageBox.Show("任務取消!"); break; } var currChannel = Math.Min(maxChannel, (channels - j * maxChannel));//兩者取其小的 TaskFactory taskFactory = new TaskFactory(); Task[] tasks = new Task[currChannel]; for (int i = 0; i < currChannel; i++) { var subData = tmpEmails.Skip((i + j * maxChannel) * maxLength).Take(maxLength).ToList(); tasks[i] = new Task(() => doSave(subData, cts.Token), cts.Token); } taskFactory.ContinueWhenAll(tasks, x => new Action(() => lblProgress.Text = "* 已完成 " + ((100 * (k + 1) / times)) + "%").InvokeRun(this), CancellationToken.None); Array.ForEach(tasks, x => x.Start()); } SetControlEnable(true);}
c#執行並行任務之Parallel與TaskFactory