C# 在 for 循环期间检查取消标记
C# check for cancellation token during for loop
我不完全理解取消令牌,但我相信这是我需要使用的。
我有一个充满文件路径的列表框,以及一个遍历列表框中每个文件路径并根据文件类型执行不同方法的方法 (ProcesstListSort
)。 ProcessListSort
是从另一种方法调用的,即通过单击按钮调用的。我试图在后台任务中 运行 BeginEverything
因为它锁定了 UI。在这种情况下实施取消令牌检查的最佳位置是什么?
单击此按钮启动进程:
public async void button1_Click(object sender, EventArgs e)
{
Task task1 = new Task(BeginEverything);
task1.Start();
await task1;
}
启动这个:
public void BeginEverything()
{
CreateThing1();
CreateThing2();
ProcessListSort(); //This is the one I think I need to interrupt because it's the longest
CreateThing3();
CreateThing4();
}
这里启动最长的任务(根据文件类型排序文件和执行其他方法,将文件路径传递给其他方法):
public void ProcessListSort()
{
for (int i = 0; i < listBox2.Items.Count; i++)
{
string p = listBox2.Items[i].ToString();
FileAttributes attr = File.GetAttributes(p);
if (p.EndsWith(".zip"))
{
Method1(p);
}
if (p.EndsWith(".txt"))
{
Method2(p);
}
if ((attr & FileAttributes.Directory) == FileAttributes.Directory)
{
Method3(p);
}
else
{
Method4(p);
}
}
}
点击“取消”按钮后立即取消是最理想的,但我会满足于在 ProcessedListSort
中处理的每个文件之间进行取消。我认为问题是我正在使用其他方法的 运行ning 方法,我不确定是否需要应用取消检查。我得到的最接近的是它看到取消标记的地方,但只是在所有内容都已执行后才“取消”。
非常感谢任何其他建议或指向替代方法的链接。我知道我做错了很多事情。
您必须创建一个 CancellationTokenSource
,然后将 CancellationToken
传递给您要取消的方法。
private CancellationTokenSource _cts =
new CancellationTokenSource( );
public async void OnClick( object sender, EventArgs args )
{
// Disable your button here.
var token = _cts.Token;
try { await Task.Run( ( ) => LongRunning( token ), token ); }
catch( OperationCanceledException )
{
Console.WriteLine( "Task was cancelled" );
}
// Enable your button here.
}
public void OnCancel( object sender, EventArgs args )
{
_cts.Cancel( );
_cts.Dispose( );
_cts = new CancellationTokenSource( );
}
public void LongRunning( CancellationToken token = default )
{
// You can either check for cancellation
// or throw if cancelled.
// If cancellation is requested this will throw an
// OperationCanceledException.
token.ThrowIfCancellationRequested( );
// If you don't want to throw you can check the
// CancellationToken to see if cancellation was requested.
if ( token.IsCancellationRequested )
return;
// You can also pass the token to other methods that
// you want to observe cancellation.
AnotherLongRunning( token );
}
我不完全理解取消令牌,但我相信这是我需要使用的。
我有一个充满文件路径的列表框,以及一个遍历列表框中每个文件路径并根据文件类型执行不同方法的方法 (ProcesstListSort
)。 ProcessListSort
是从另一种方法调用的,即通过单击按钮调用的。我试图在后台任务中 运行 BeginEverything
因为它锁定了 UI。在这种情况下实施取消令牌检查的最佳位置是什么?
单击此按钮启动进程:
public async void button1_Click(object sender, EventArgs e)
{
Task task1 = new Task(BeginEverything);
task1.Start();
await task1;
}
启动这个:
public void BeginEverything()
{
CreateThing1();
CreateThing2();
ProcessListSort(); //This is the one I think I need to interrupt because it's the longest
CreateThing3();
CreateThing4();
}
这里启动最长的任务(根据文件类型排序文件和执行其他方法,将文件路径传递给其他方法):
public void ProcessListSort()
{
for (int i = 0; i < listBox2.Items.Count; i++)
{
string p = listBox2.Items[i].ToString();
FileAttributes attr = File.GetAttributes(p);
if (p.EndsWith(".zip"))
{
Method1(p);
}
if (p.EndsWith(".txt"))
{
Method2(p);
}
if ((attr & FileAttributes.Directory) == FileAttributes.Directory)
{
Method3(p);
}
else
{
Method4(p);
}
}
}
点击“取消”按钮后立即取消是最理想的,但我会满足于在 ProcessedListSort
中处理的每个文件之间进行取消。我认为问题是我正在使用其他方法的 运行ning 方法,我不确定是否需要应用取消检查。我得到的最接近的是它看到取消标记的地方,但只是在所有内容都已执行后才“取消”。
非常感谢任何其他建议或指向替代方法的链接。我知道我做错了很多事情。
您必须创建一个 CancellationTokenSource
,然后将 CancellationToken
传递给您要取消的方法。
private CancellationTokenSource _cts =
new CancellationTokenSource( );
public async void OnClick( object sender, EventArgs args )
{
// Disable your button here.
var token = _cts.Token;
try { await Task.Run( ( ) => LongRunning( token ), token ); }
catch( OperationCanceledException )
{
Console.WriteLine( "Task was cancelled" );
}
// Enable your button here.
}
public void OnCancel( object sender, EventArgs args )
{
_cts.Cancel( );
_cts.Dispose( );
_cts = new CancellationTokenSource( );
}
public void LongRunning( CancellationToken token = default )
{
// You can either check for cancellation
// or throw if cancelled.
// If cancellation is requested this will throw an
// OperationCanceledException.
token.ThrowIfCancellationRequested( );
// If you don't want to throw you can check the
// CancellationToken to see if cancellation was requested.
if ( token.IsCancellationRequested )
return;
// You can also pass the token to other methods that
// you want to observe cancellation.
AnotherLongRunning( token );
}