我有一个函数在串行端口上调用读取或写入请求,然后返回读取的值。我正在使用Commstudio express(我正在实现Commstudio中的一个类),但它的超时功能似乎根本不起作用,所以我正在尝试实现自己的超时。目前我有一个定时器,根据请求设置读取或写入端口,如果定时器熄灭,回调将关闭连接导致异常。我试图让计时器的回调抛出一个异常,但异常需要通过调用原始读/写函数的线程传播,所以这样,它起作用,但我觉得它很混乱,那里必须是做我想做的更好的方式。
答案 0 :(得分:34)
这是一个通用的解决方案,允许您在超时中包装任何方法:
http://kossovsky.net/index.php/2009/07/csharp-how-to-limit-method-execution-time/
它使用有用的Thread.Join重载,它接受超时(以毫秒为单位)而不是手动使用定时器。我唯一不同的做法是交换成功标志和结果值以匹配TryParse模式,如下所示:
public static T Execute<T>(Func<T> func, int timeout)
{
T result;
TryExecute(func, timeout, out result);
return result;
}
public static bool TryExecute<T>(Func<T> func, int timeout, out T result)
{
var t = default(T);
var thread = new Thread(() => t = func());
thread.Start();
var completed = thread.Join(timeout);
if (!completed) thread.Abort();
result = t;
return completed;
}
这就是你如何使用它:
var func = new Func<string>(() =>
{
Thread.Sleep(200);
return "success";
});
string result;
Debug.Assert(!TryExecute(func, 100, out result));
Debug.Assert(result == null);
Debug.Assert(TryExecute(func, 300, out result));
Debug.Assert(result == "success");
答案 1 :(得分:2)
听起来你正在进行阻塞读/写。你想要做的是一个非阻塞的读/写。
可能有一种方法可以告诉com端口你想要非阻塞。
你确定超时不适用于commstudio吗?也许你必须做一些特殊的事情来初始化它们。
在任何情况下,您都希望尽可能多地读取数据,如果没有可用超时(取决于超时的值)。你想要在没有可用数据且没有错误的情况下保持循环,然后在没有任何可用的情况下返回超时条件。
让你的read函数返回一个整数。负值=错误值,例如-1 =超时,正读取的字节数...至少就像我做的那样。
答案 2 :(得分:0)
对于comport你可以测试是否有任何可用的东西然后做一个读取而不是做阻塞读取而不知道还有什么。类似的东西:
Int32 timeout=1000;
String result = String.Empty';
while (timeout!=0) {
if (Serial.BytesToRead>0) {
while (Serial.BytesToRead>0) {
result+=Serial.ReadChar();
}
break;
}
Thread.Sleep(1);
timeout--;
}
答案 3 :(得分:0)
如果有人想在VB.Net中这样做,请不要听那些说它无法完成的人! 您可能需要更改通用参数以适合您的使用案例。
Public Shared Function Execute(Of I, R)(Func As Func(Of I, R), Input As I, TimeOut As Integer) As R
Dim Result As R
TryExecute(Func, Input, TimeOut, Result)
Return Result
End Function
Public Shared Function TryExecute(Of I, R)(Func As Func(Of I, R), Input As I, TimeOut As Integer, ByRef Result As R) As Boolean
Dim OutParam As R = Nothing
Dim Thread As New System.Threading.Thread(Sub() InlineAssignHelper(OutParam, Func(Input)))
Thread.IsBackground = True
Thread.Start()
Dim Completed As Boolean = Thread.Join(TimeOut)
If Not Completed Then Thread.Abort()
Result = OutParam
Return Completed
End Function
Private Shared Function InlineAssignHelper(Of T)(ByRef Target As T, ByVal Value As T) As T
Target = Value
Return Value
End Function
以及如何使用它的一个例子(我的是Regex.Match
,如果模式包含太多的外卡,它有时会永远不会落地:
Public Function Match(Input As String) As Match
If Regex Is Nothing Then Return Nothing
Dim RegexMatch As System.Text.RegularExpressions.Match = Nothing
Dim Func As New Func(Of String, System.Text.RegularExpressions.Match)(Function(x As String) Regex.Match(x))
If Runtime.TryExecute(Of String, System.Text.RegularExpressions.Match)(Func, Input, 2000, RegexMatch) Then
Return (New Match(Me, Regex.Match(Input), Input))
Else
Return Nothing
End If
End Function