我是TPL世界的新手,我做了那段代码:
var myItems = myWpfDataGrid.SelectedItems;
this.Dispatcher.BeginInvoke(new Action(() =>
{
var scheduler = new LimitedConcurrencyLevelTaskScheduler(5);
TaskFactory factory = new TaskFactory(scheduler);
foreach (MyItem item in myItems)
{
Task myTask = factory.StartNew(() =>
DoLoooongWork(item)
).ContinueWith((t) =>
{
Debug.WriteLine(t.Exception.Message);
if (t.Exception.InnerException != null)
{
Debug.WriteLine(t.Exception.InnerException.Message);
}
},
TaskContinuationOptions.OnlyOnFaulted);
}
}), null);
唯一访问gui的是“ var myItems = myWpfDataGrid.SelectedItems; ” 它是只读的!函数“DoLoooongWork()”可以访问串行端口等。它是一个独立的SDK函数,不能访问GUI。我知道“Dispatcher.BeginInvoke”有点多余,但我不知道我能做什么,或者我做错了什么。这段代码的唯一原因是在执行“DoLoooongWork()”时释放GUI,但GUI被冻结了!
该代码出了什么问题?
修改
感谢@Euphoric的帮助,我发现了与该帖子类似的问题: COM Interop hang freezes entire COM system. How to cancel COM call
答案 0 :(得分:3)
我假设DoLoooongWork
内的一些对象需要线程亲和力和消息抽取。试试我的ThreadWithAffinityContext
,看看是否有帮助,请像这样使用它:
private async void Button_Click(object sender, EventArgs e)
{
try
{
using (var staThread = new Noseratio.ThreadAffinity.ThreadWithAffinityContext(
staThread: true, pumpMessages: true))
{
foreach (MyItem item in myItems)
{
await staThread.Run(() =>
{
DoLoooongWork(item);
}, CancellationToken.None);
}
}
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
More info about ThreadWithAffinityContext
[更新] 您在评论中提到DoLoooongWork
内的代码如下所示:
zkemkeeper.CZKEM axCZKEM1 = new zkemkeeper.CZKEM();
axCZKEM1.Connect_Net(ip, port);
之前我从未听说过“zkemkeeper”,但我做了一个简短的搜索,发现this question。显然,Connect_Net
只建立连接并启动会话,而整个通信逻辑通过某些事件异步发生,正如该问题所暗示的那样:
bIsConnected = axCZKEM1.Connect_Net("192.168.0.77", Convert.ToInt32("4370"));
if (bIsConnected == true)
{
iMachineNumber = 1;
if (axCZKEM1.RegEvent(iMachineNumber, 65535))
{
this.axCZKEM1.OnFinger += new kemkeeper._IZKEMEvents_OnFingerEventHandler(axCZKEM1_OnFinger);
this.axCZKEM1.OnVerify += new zkemkeeper._IZKEMEvents_OnVerifyEventHandler(axCZKEM1_OnVerify);
// ...
}
}
那将是一个完全不同的故事。如果是这种情况,请发表评论并且您仍对某些解决方案感兴趣。
答案 1 :(得分:1)
我有一种预感,使用串口的东西会尝试使用应用程序的事件循环来完成它的工作。所以它实际上绕过了整个调度程序和线程系统并阻止了应用程序。我在这个领域没有经验,所以我不知道如何解决它,但这是另一个问题。