我正在尝试使用以下技术让一个工作人员任务执行某些操作,超时10秒并且不会阻止应用程序。
internal void ReadAll()
{
var data = new byte[1];
Task.Factory.StartNew(() =>
{
var ct = new CancellationTokenSource();
var ReadAllTask = Task.Factory.StartNew(() =>
{
// Read all information
// [omit communication exchange via COM port]
ct.Cancel();
}, ct.Token);
// First thread waiting 10s for the worker to finish
ReadAllTask.Wait(10000, ct.Token);
if (ReadAllTask.Status == TaskStatus.RanToCompletion)
{
ReadAllComplete?.Invoke(true);
}
else
{
ct.Cancel();
ReadAllComplete?.Invoke(false);
}
});
}
按下按钮调用此方法。在我看来,在调试配置工作正常,但不是在发布配置,其中"第一个线程"永远不会等待,也不会抛出任何事件。
答案 0 :(得分:2)
您的代码可能比当前版本简单得多。为事件制作非阻止方法的最简单方法是使用async
关键字对其进行标记,并使用await
关键字从asynchronous read operation属性启动SerialPort.BaseStream
。
此外,CancellationTokenSource
可以随着时间创建,之后会自动取消,而取消的正确方法是调用CancellationToken.ThrowIfCancellationRequested方法。 async/await
机制将在UI上下文中调用事件,因此代码可能是这样的:
// async void is a recommended way to use asynchronous event handlers
private async void btnReadAll_Click(object sebder, EventArgs e)
{
var data = new byte[2];
// cancel source after 10 seconds
var cts = new CancellationTokenSource(10000);
// Read all information
// [omit communication exchange via COM port]
// async operation with BaseStream
var result = await SerialPort.BaseStream.ReadAsync(data, 0, 2, cts.Token);
/*
* if you can't use the BaseStream methods, simply call this method here
* cts.Token.ThrowIfCancellationRequested();
*/
// this code would run only if everything is ok
// check result here in your own way
var boolFlag = result != null;
ReadAllComplete?.Invoke(boolFlag);
}
答案 1 :(得分:1)
这里只是一个快速重写,用于删除事件并将异步IO中的同步IO API包装起来。如果可能的话,您应该切换到真正的异步API并删除con = new OracleConnection();
con.ConnectionString = "...";
con.Open(); //<--- do this
。
Task.Run
答案 2 :(得分:0)
阅读我的问题的评论和答案我学到了一些有用的东西来解决我的问题:
现在我的代码更简单,它可以工作:
private void Read_All_Button_Click(object sender, RoutedEventArgs e)
{
// Start timedout task that will send all necessary commands
CancellationTokenSource cts = new CancellationTokenSource(10000);
Task.Run(() =>
{
oCommandSets.ReadAll(cts);
}, cts.Token);
}
和
internal void ReadAll(CancellationTokenSource cts)
{
// [communication]
if (cts.IsCancellationRequested)
{
ReadAllComplete?.Invoke(false);
}
else
{
ReadAllComplete?.Invoke(true);
}
}
无论如何,我需要了解有关多线程的更多信息。