2013-12-18 55 views
2

嗨即时尝试运行方法异步以便计时持续时间并取消方法如果超时超时。在另一个线程中执行时间方法,并在超时时中止

我试图使用异步实现这一点,并等待。但没有运气。也许IM过度设计这个,任何输入可以理解

应当指出的是,我不能改变的接口“TheirInterface”(因此得名)

到目前为止的代码:

using System; 
using System.Diagnostics; 

public interface TheirInterface 
{ 
    void DoHeavyWork(); 
} 

public class Result 
{ 
    public TimeSpan Elapsed { get; set; } 
    public Exception Exception { get; set; } 

    public Result(TimeSpan elapsed, Exception exception) 
    { 
     Elapsed = elapsed; 
     Exception = exception; 
    } 
} 

public class TaskTest 
{ 
    public void Start(TheirInterface impl) 
    { 
     int timeout = 10000; 

     // TODO 
     // Run HeavyWorkTimer(impl) 
     // 
     // Wait for timeout, will be > 0 
     // 
     // if timeout occurs abortheavy 
    } 

    public Result HeavyWorkTimer(TheirInterface impl) 
    { 
     var watch = new Stopwatch(); 

     try 
     { 
      watch.Start(); 
      impl.DoHeavyWork(); 
      watch.Stop(); 
     } 
     catch (Exception ex) 
     { 
      watch.Stop(); 

      return new Result(watch.Elapsed, ex); 
     } 

     return new Result(watch.Elapsed, null); 
    } 
} 
+4

你应该通过在'TheirInterface.DoHeavyWork'中要求一个'CancellationToken'作为参数来强制执行协作取消,并把它变成'Task' ...否则,据我所知,没有干净的方法来'放弃“在同一过程中运行的其他操作。 –

+0

@PatrykĆwiek良好的通话,我会建议这个接口的所有者。 –

+2

@PatrykĆwiek拥有最佳的解决方案。您的其他选择是:启动专用线程并在超时时中止它(可能会破坏应用程序域);启动一个专门的应用程序域并在超时时卸载它(这可能会导致进程不稳定);启动一个单独的进程并在超时时终止它(这是唯一真正安全的方法来终止不可撤销的代码)。 –

回答

0

你想创建一个定时器,当它到期时取消该线程。在没有合作取消的情况下,您必须致电Thread.Abort,这并不理想。我会假设你知道中止线程所涉及的危险。

public Result HeavyWorkTimer(TheirInterface impl) 
{ 
    var watch = new Stopwatch(); 
    Exception savedException = null; 

    var workerThread = new Thread(() => 
    { 
     try 
     { 
      watch.Start(); 
      impl.DoHeavyWork(); 
      watch.Stop(); 
     } 
     catch (Exception ex) 
     { 
      watch.Stop(); 
      savedException = ex; 
     } 
    }); 

    // Create a timer to kill the worker thread after 5 seconds. 
    var timeoutTimer = new System.Threading.Timer((s) => 
     { 
      workerThread.Abort(); 
     }, null, TimeSpan.FromSeconds(5), TimeSpan.Infinite); 

    workerThread.Start(); 

    workerThread.Join(); 

    return new Result(watch.Elapsed, savedException); 
} 

请注意,如果中止该线程,该线程将获得ThreadAbortException

如果您可以说服接口所有者添加协作取消,那么您可以更改定时器回调,以便它请求取消令牌而不是调用Thread.Abort

+0

感谢您的意见,不幸的是界面所有者不想支持取消操作。我不敢放弃线索,不知道后果。因此,我不是调用workerThread.Abort(),而是决定引发一个事件,指示超时并通知用户。 –

相关问题