ParallelOptions的一个成员是CancellationToken,其值应在Parallel.ForEach的lambda函数中访问。
使用它需要在调用Parallel.ForEach之前实例化CacellationToken,那么为什么不能直接在ForEach的Lambda函数中访问该局部变量?
e.g。而不是:
uniform sampler2D texture;
void main() {
gl_FragColor = texture2D(texture, gl_TexCoord[0].st) * vec4(1,0,0,1);
}
为什么我不能使用:
var ct = new CancellationToken();
var options = new ParallelOptions { CancellationToken = ct }
Parallel.ForEach(source, options, (item) =>
{
options.ct.ThrowIfCancellationRequested();
})
是否只是一个存放令牌的方便地方,或者这个设计是否有一些潜在的原因?
答案 0 :(得分:4)
如果您告诉Parallel.ForEach
CancellationToken
,则可以在取消令牌时停止处理。您可能不希望从循环中抛出异常 - 您可能只想自己忽略取消令牌,并且只是希望处理您的项目的子集。
例如:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
class Test
{
static void Main()
{
var cts = new CancellationTokenSource(TimeSpan.FromSeconds(3));
var items = Enumerable.Range(0, 100).ToList();
Parallel.ForEach(items, new ParallelOptions { CancellationToken = cts.Token },
item =>
{
Console.WriteLine(item);
Thread.Sleep(1000);
});
}
}
这将在三秒后以OperationCanceledException
完成(而不是AggregateException
如果某个/某些单个任务失败,则会收到你的Parallel.ForEach
- 但是行动机构本身并没有; t需要知道取消令牌。当然,如果你有一个昂贵的操作,你不想为完成的最终项目不必要地完成,你可以自己监控令牌,但你可以让private void button1_Click(object sender, EventArgs e)
{
SqlConnection con = new SqlConnection(conString);
con.Open();
if (con.State == System.Data.ConnectionState.Open)
{
SqlCommand cmd = new SqlCommand("select * from Employee_Details where email = '"+txtEmail.Text+"' and password = '"+txtPass.Text+"'", con);
SqlDataReader dr;
dr = cmd.ExecuteReader();
int count = 0;
while(dr.Read())
{
count += 1;
}
if (count == 1)
{
con.Close();
con.Open();
SqlCommand cmd_user = new SqlCommand("select id from Employee_Details where email = '" + txtEmail.Text + "' and password = '" + txtPass.Text + "'", con);
SqlDataReader reader = cmd_user.ExecuteReader();
while (reader.Read())
{
string user_id = Convert.ToString(reader["id"]);
}
MessageBox.Show("Log in Successfull");
this.Hide();
MainMenu mn = new MainMenu();
mn.ShowDialog();
}
注意并抛出异常本身。
答案 1 :(得分:-2)
“乔恩·斯基特”的答案并非在所有情况下都正确。 来自ParallelOptions的令牌源取消,直到所有任务完成后才中断Parallel.ForEach循环。 要中断循环,您必须使用例如调用token.ThrowIfCancellationRequested()或完成所有任务的方法。