运行 方法安全取消?
Run method Safe cancellation?
我想在与 GUI 不同的线程中调用函数。
我使用了下面的代码来触发函数:
private void button1_Click(object sender, EventArgs e)
{
tokensource = new CancellationTokenSource();
var token = tokensource.Token;
Task.Run(()=>foo() , token);
}
private void foo()
{
// Uses some resources
}
private void button2_Click(object sender, EventArgs e)
{
tokenSource.Cancel();
}
任务取消时如何安全关闭foo()
中占用的资源?
您在任务中启动的代码应该负责考虑取消。您传递给 "Task.Run" 方法的取消令牌将仅用于取消未启动的任务。
您还需要将令牌传递给函数。传递给 Task.Run 的取消令牌不会中止已经 运行 的任务,它会阻止计划任务从 运行.
在foo
里面,可以检查token是否取消和return,或者抛出异常。您可以使用 using
块来安全地处理资源。例如:
private void foo(CancellationToken token)
{
using(var reader=new StreamReader(somePath)
{
string line;
// Read the line if no cancellation was requested
while (!token.IsCancellationRequested && (line = sr.ReadLine()) != null)
{
Console.WriteLine(line);
}
}
}
此代码仅在未请求取消时才读取一行,否则 return 会安静地读取一行
您还可以通过调用 CancellationToken.ThrowIfCancellationRequested
抛出 OperationCancelledException
private void foo(CancellationToken token)
{
using(var reader=new StreamReader(somePath)
{
string line;
// Read the line if no cancellation was requested
while ((line = sr.ReadLine()) != null)
{
token.ThrowIfCancellationRequested();
Console.WriteLine(line);
}
}
}
这将抛出异常,当检索到任务的结果时,调用代码将引发该异常,例如使用 await Task.Run(..)
或 Task.Run(..).Wait()
时
您的方法应该像这样处理 CancellationToken:
public static void Main(string[] args)
{
var tokenSource = new CancellationTokenSource();
Console.WriteLine("Press CTRL+C to cancel important work");
Console.CancelKeyPress += (sender, eventArgs) => {
eventArgs.Cancel = true;
tokenSource.Cancel();
};
var task = Task.Run(() => foo(tokenSource.Token));
task.Wait();
WaitFor(action: "exit");
}
private static void foo(CancellationToken token)
{
const int Times = 10;
for (var x = 0; x < Times && token.IsCancellationRequested == false; ++x) {
Console.WriteLine("Important work");
Task
.Delay(200)
.Wait();
}
Console.WriteLine($"Free resources: {token.IsCancellationRequested}");
}
public static void WaitFor(ConsoleKey consoleKey = ConsoleKey.Escape, string action = "continue")
{
Console.Write($"Press {consoleKey} to {action} ...");
var consoleKeyInfo = default(ConsoleKeyInfo);
do {
consoleKeyInfo = Console.ReadKey(true);
}
while (Equals(consoleKeyInfo.Key, consoleKey) == false);
Console.WriteLine();
}
BR
incureforce
我想在与 GUI 不同的线程中调用函数。
我使用了下面的代码来触发函数:
private void button1_Click(object sender, EventArgs e)
{
tokensource = new CancellationTokenSource();
var token = tokensource.Token;
Task.Run(()=>foo() , token);
}
private void foo()
{
// Uses some resources
}
private void button2_Click(object sender, EventArgs e)
{
tokenSource.Cancel();
}
任务取消时如何安全关闭foo()
中占用的资源?
您在任务中启动的代码应该负责考虑取消。您传递给 "Task.Run" 方法的取消令牌将仅用于取消未启动的任务。
您还需要将令牌传递给函数。传递给 Task.Run 的取消令牌不会中止已经 运行 的任务,它会阻止计划任务从 运行.
在foo
里面,可以检查token是否取消和return,或者抛出异常。您可以使用 using
块来安全地处理资源。例如:
private void foo(CancellationToken token)
{
using(var reader=new StreamReader(somePath)
{
string line;
// Read the line if no cancellation was requested
while (!token.IsCancellationRequested && (line = sr.ReadLine()) != null)
{
Console.WriteLine(line);
}
}
}
此代码仅在未请求取消时才读取一行,否则 return 会安静地读取一行
您还可以通过调用 CancellationToken.ThrowIfCancellationRequested
抛出 OperationCancelledExceptionprivate void foo(CancellationToken token)
{
using(var reader=new StreamReader(somePath)
{
string line;
// Read the line if no cancellation was requested
while ((line = sr.ReadLine()) != null)
{
token.ThrowIfCancellationRequested();
Console.WriteLine(line);
}
}
}
这将抛出异常,当检索到任务的结果时,调用代码将引发该异常,例如使用 await Task.Run(..)
或 Task.Run(..).Wait()
您的方法应该像这样处理 CancellationToken:
public static void Main(string[] args)
{
var tokenSource = new CancellationTokenSource();
Console.WriteLine("Press CTRL+C to cancel important work");
Console.CancelKeyPress += (sender, eventArgs) => {
eventArgs.Cancel = true;
tokenSource.Cancel();
};
var task = Task.Run(() => foo(tokenSource.Token));
task.Wait();
WaitFor(action: "exit");
}
private static void foo(CancellationToken token)
{
const int Times = 10;
for (var x = 0; x < Times && token.IsCancellationRequested == false; ++x) {
Console.WriteLine("Important work");
Task
.Delay(200)
.Wait();
}
Console.WriteLine($"Free resources: {token.IsCancellationRequested}");
}
public static void WaitFor(ConsoleKey consoleKey = ConsoleKey.Escape, string action = "continue")
{
Console.Write($"Press {consoleKey} to {action} ...");
var consoleKeyInfo = default(ConsoleKeyInfo);
do {
consoleKeyInfo = Console.ReadKey(true);
}
while (Equals(consoleKeyInfo.Key, consoleKey) == false);
Console.WriteLine();
}
BR incureforce