这种在关闭端口之前使用任务取消的方法是否正确?
Is this way of using Task cancellation before closing port correct?
我有一个 C# GUI 应用程序,当单击按钮然后 MyMethod 启动时 运行 异步方式,它连续(在 do while 循环内)调用 MyTask。 MyTask 从端口写入和读取数据。并将这些数据传递给 MyProgressMethod 以进行进一步处理。
我想实现一个按钮,它首先 cancel/stop MyTask 然后关闭端口。
作为异步方式的新手,我依赖于一些我偶然发现的在线示例,其余的则难以掌握。根据我阅读的内容,我想出了以下方法来通过按钮实现取消。但是我不是很明白这个机制,想知道下面的方式是否正确:
在 class 的开头声明 CancellationTokenSource 对象:
CancellationTokenSource my_cancelationTokenSource = null;
按钮点击事件。按钮事件调用 MyMethod:
private void Button_Click(object sender, RoutedEventArgs e)
{
//Some code
MyMethod();
}
MyMethod 每秒调用 MyTask 并将数据传递给 MyProgressMethod:
private async void MyMethod()
{
my_cancelationTokenSource = new CancellationTokenSource();
do
{
await Task.Delay(1000);
//Process some code
byte[] my_received_data = await MyTask(my_sent_data, my_cancelationTokenSource.Token);
MyProgressMethod(my_received_data, my_sent_data);
}
while (true);
}
MyTask读写端口(关闭端口前需要取消):
private async Task<byte[]> MyTask(byte[] my_sent_data, CancellationToken cancelToken)
{
await Task.Delay(200, cancelToken);//??? What should happen here?
//Some code
}
取消任务关闭端口的按钮事件:
private void Button_Disconnect_Click(object sender, RoutedEventArgs e)
{
my_cancelationTokenSource.Cancel();
if (my_port.IsOpen)
{
my_port.Close();
}
}
如何优化此代码的稳定性?(即端口应仅在任务取消后关闭)
这里的解决方法是不要直接从Disconnect按钮关闭端口。相反,取消令牌,并在 MyMethod
:
中捕获 OperationCanceledException
private CancellationTokenSource my_cancelationTokenSource;
private async void MyMethod()
{
my_cancelationTokenSource = new CancellationTokenSource();
try
{
while (true)
{
await Task.Delay(1000, my_cancelationTokenSource.Token);
//Process some code
byte[] my_received_data = await MyTask(my_sent_data, my_cancelationTokenSource.Token);
MyProgressMethod(my_received_data, my_sent_data);
}
}
catch (OperationCanceledException)
{
try
{
my_cancelationTokenSource.Dispose();
my_cancelationTokenSource = null;
my_port.Dispose();
}
catch { }
}
}
private void Button_Disconnect_Click(object sender, RoutedEventArgs e)
{
my_cancelationTokenSource?.Cancel();
}
备注:
my_cancelationTokenSource
成为字段而不是局部变量。
- 也将令牌传递给
Task.Delay
函数。 (目前还不清楚为什么你需要延迟,通常你只是等待端口上的响应)。
- 我不知道你到底想在取消时做什么,我会留给你。
try/catch
关闭端口,您应该通过 Dispose
关闭端口,以防它抛出。
我有一个 C# GUI 应用程序,当单击按钮然后 MyMethod 启动时 运行 异步方式,它连续(在 do while 循环内)调用 MyTask。 MyTask 从端口写入和读取数据。并将这些数据传递给 MyProgressMethod 以进行进一步处理。
我想实现一个按钮,它首先 cancel/stop MyTask 然后关闭端口。
作为异步方式的新手,我依赖于一些我偶然发现的在线示例,其余的则难以掌握。根据我阅读的内容,我想出了以下方法来通过按钮实现取消。但是我不是很明白这个机制,想知道下面的方式是否正确:
在 class 的开头声明 CancellationTokenSource 对象:
CancellationTokenSource my_cancelationTokenSource = null;
按钮点击事件。按钮事件调用 MyMethod:
private void Button_Click(object sender, RoutedEventArgs e)
{
//Some code
MyMethod();
}
MyMethod 每秒调用 MyTask 并将数据传递给 MyProgressMethod:
private async void MyMethod()
{
my_cancelationTokenSource = new CancellationTokenSource();
do
{
await Task.Delay(1000);
//Process some code
byte[] my_received_data = await MyTask(my_sent_data, my_cancelationTokenSource.Token);
MyProgressMethod(my_received_data, my_sent_data);
}
while (true);
}
MyTask读写端口(关闭端口前需要取消):
private async Task<byte[]> MyTask(byte[] my_sent_data, CancellationToken cancelToken)
{
await Task.Delay(200, cancelToken);//??? What should happen here?
//Some code
}
取消任务关闭端口的按钮事件:
private void Button_Disconnect_Click(object sender, RoutedEventArgs e)
{
my_cancelationTokenSource.Cancel();
if (my_port.IsOpen)
{
my_port.Close();
}
}
如何优化此代码的稳定性?(即端口应仅在任务取消后关闭)
这里的解决方法是不要直接从Disconnect按钮关闭端口。相反,取消令牌,并在 MyMethod
:
OperationCanceledException
private CancellationTokenSource my_cancelationTokenSource;
private async void MyMethod()
{
my_cancelationTokenSource = new CancellationTokenSource();
try
{
while (true)
{
await Task.Delay(1000, my_cancelationTokenSource.Token);
//Process some code
byte[] my_received_data = await MyTask(my_sent_data, my_cancelationTokenSource.Token);
MyProgressMethod(my_received_data, my_sent_data);
}
}
catch (OperationCanceledException)
{
try
{
my_cancelationTokenSource.Dispose();
my_cancelationTokenSource = null;
my_port.Dispose();
}
catch { }
}
}
private void Button_Disconnect_Click(object sender, RoutedEventArgs e)
{
my_cancelationTokenSource?.Cancel();
}
备注:
my_cancelationTokenSource
成为字段而不是局部变量。- 也将令牌传递给
Task.Delay
函数。 (目前还不清楚为什么你需要延迟,通常你只是等待端口上的响应)。 - 我不知道你到底想在取消时做什么,我会留给你。
try/catch
关闭端口,您应该通过Dispose
关闭端口,以防它抛出。