[英]How to stop the execution of a method after a specific time?
如果方法在一段有限的時間內沒有完成,我需要停止執行。
為了完成這項工作,我可以用這種方式使用Thread.Abort
方法:
void RunWithTimeout(ThreadStart entryPoint, int timeout)
{
var thread = new Thread(() =>
{
try
{
entryPoint();
}
catch (ThreadAbortException)
{ }
}) { IsBackground = true };
thread.Start();
if (!thread.Join(timeout))
thread.Abort();
}
鑒於我使用的是.NET 3.5,還有更好的方法嗎?
編輯:在這里注釋我的entryPoint
,但我正在為任何entryPoint
尋找一個好方法。
void entryPoint()
{
// I can't use ReceiveTimeout property
// there is not a ReceiveTimeout for the Compact Framework
socket.Receive(...);
}
答案取決於“工作”。 如果工作是可以安全停止的(即不是一些I / O阻塞操作) - 使用Backgroundworker.CancelAsync(...)
如果你確實需要努力 - 我會考慮使用Process
,在這種情況下, Aborting
過程更干凈 - 而且process.WaitForExit(timeout)
是你的朋友。
建議的TPL很棒,但遺憾的是在.Net 3.5中不存在。
編輯:您可以使用Reactive Extensions來遵循Jan de Vaan的建議。
這是我的'動作超時'剪輯 - 它主要是供其他人評論:
public static bool WaitforExit(this Action act, int timeout)
{
var cts = new CancellationTokenSource();
var task = Task.Factory.StartNew(act, cts.Token);
if (Task.WaitAny(new[] { task }, TimeSpan.FromMilliseconds(timeout)) < 0)
{ // timeout
cts.Cancel();
return false;
}
else if (task.Exception != null)
{ // exception
cts.Cancel();
throw task.Exception;
}
return true;
}
編輯 :顯然這不是OP想要的。 這是我試圖設計一個'可取消的'套接字接收器:
public static class Ext
{
public static object RunWithTimeout<T>(Func<T,object> act, int timeout, T obj) where T : IDisposable
{
object result = null;
Thread thread = new Thread(() => {
try { result = act(obj); }
catch {} // this is where we end after timeout...
});
thread.Start();
if (!thread.Join(timeout))
{
obj.Dispose();
thread.Join();
}
return result;
}
}
class Test
{
public void SocketTimeout(int timeout)
{
using (var sock = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp))
{
Object res = Ext.RunWithTimeout(EntryPoint, timeout, sock);
}
}
private object EntryPoint(Socket sock)
{
var buf = new byte[256];
sock.Receive(buf);
return buf;
}
}
Thread.Abort通常是一個糟糕的解決方案 。 您應該使用一個標志來指示操作是否被取消,並在您的entryPoint函數中進行檢查。
class Program
{
static void Main(string[] args)
{
RunWithTimeout((token) =>
{
Thread.Sleep(2000);
if (token.Cancel)
{
Console.WriteLine("Canceled");
}
}, 1000);
Console.ReadLine();
}
private class Token
{
public bool Cancel { get; set; }
}
static void RunWithTimeout(Action<Token> entryPoint, int timeout)
{
Token token = new Token();
var thread = new Thread(() => entryPoint(token)) { IsBackground = true };
thread.Start();
if (!thread.Join(timeout))
token.Cancel = true;
}
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.