【发布时间】:2017-03-11 12:10:39
【问题描述】:
我有一种与 HID 设备通信以检索序列号的方法,但是,如果 HID 设备“存在”但不像使用 BT 时常见的那样处于活动状态,则对序列号的调用将被阻塞并且只是坐下在那里。
我想调用我的方法,但让它超时,如果失败则返回空序列号,如果成功则返回正确序列号。
Task.Run 完成了大部分任务,但不会在任务挂起时终止任务,从而使我的应用程序无法退出。
var task = Task.Run(() => GetSerialStringWorker(device));
if (task.Wait(TimeSpan.FromMilliseconds(300)))
return task.Result;
else
{
//Need to be able to kill the task here!
return "00:00:00:00:00:00";
}
不能使用取消令牌,因为获取序列号的代码是外部库的一部分,不接受取消。
也试过这个,但它阻塞在 thread.Join() 上,并且在线程中止时无法正确释放;
string sn = "00:00:00:00:00:00";
System.Timers.Timer timeoutTimer = new System.Timers.Timer() { Interval = 300 };
Thread thread = new Thread(() =>
{
sn = GetSerialStringWorker(device);
timeoutTimer.Stop();
});
timeoutTimer.AutoReset = false;
timeoutTimer.Elapsed += (s, e) => { thread.Abort(); };
timeoutTimer.Start();
thread.Start();
thread.Join();
return sn;
好的,无论出于何种原因,上述示例中的 Join 都会使我的应用程序无法完全加载,并且只是坐在那里阻止其余的应用程序初始化。解决方案是使用 while 命令阻止它;
string sn = "";
Thread thread = new Thread(() =>
{
sn = GetSerialStringWorker(device);
});
var timeoutTimer = new System.Threading.Timer((s) =>
{
thread.Abort();
sn = "00:00:00:00:00:00";
}, null, 500, Timeout.Infinite);
thread.Start();
while (sn == "")
{
Thread.Sleep(1);
}
return sn;
这感觉真的很难看,但现在它可以工作,直到有人能找到更好的方法。
【问题讨论】:
-
@OrangeKing89 正如我所说,任务不允许堕胎。
-
我认为您可以将 .Join() 替换为事件机制。但是中止线程总是对资源存疑。
-
因为您(显然)在处理第三方/非托管代码,所以您的选择是有限的。中止线程是一个非常糟糕的主意,但是无缘无故地让线程无限期地处于活动状态也是如此。有关您可用的不良选择的讨论,请参见标记的副本。另请参阅stackoverflow.com/questions/2781484/abort-call-to-unmanaged-dll,了解有关处理不可取消的第三方呼叫的信息。
标签: c#