我想在与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()
中的已占用资源?
答案 0 :(得分:2)
您还需要将令牌传递给该函数。传递给Task.Run的取消令牌不会中止已经运行的任务,它将阻止计划任务运行。
在foo
内,您可以检查令牌是否取消并返回,或者抛出异常。您可以使用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);
}
}
}
此代码仅在未请求取消时读取一行,否则将安静地返回
您也可以通过调用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()
答案 1 :(得分:1)
你的方法应该像这样处理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
答案 2 :(得分:0)
您在任务中启动的代码应负责考虑取消。您传递到“Task.Run”方法的取消令牌将仅用于取消未启动的任务。