如何等待特定持续时间的函数执行

时间:2016-02-14 13:06:43

标签: c# wait hang

我的C#应用​​程序停止响应了很长时间,因为我在一个函数上打破了它停止的调试。

foreach (var item in list)
{
    xmldiff.Compare(item, secondary, output);
    ...
}

我猜这个功能的运行时间很长或者挂起。无论如何,我想等待一段时间(例如5秒)执行此功能,如果超过这个时间,我跳过它并转到循环中的下一个项目。我该怎么做?我发现了一些类似的问题,但它们主要用于进程或异步方法。

3 个答案:

答案 0 :(得分:2)

你可以用残酷的方式做到这一点:启动一个线程来完成工作,用超时加入它,然后中止它,如果连接不起作用。

示例:

var worker = new Thread( () => { xmlDiff.Compare(item, secondary, output); } );
worker.Start();
if (!worker.Join( TimeSpan.FromSeconds( 1 ) ))
    worker.Abort();

但要注意 - 中止线程并不好看,可能会让你的应用程序不稳定。如果可能,请尝试修改Compare以接受CancellationToken取消比较。

答案 1 :(得分:0)

我会避免直接使用线程并使用Microsoft的Reactive Extensions(NuGet“Rx-Main”)来抽象出线程的管理。

我不知道xmldiff.Compare(item, secondary, output)的确切签名但如果我假设它产生一个整数,那么我可以用Rx做到这一点:

var query =
    from item in list.ToObservable()
    from result in
        Observable
            .Start(() => xmldiff.Compare(item, secondary, output))
            .Timeout(TimeSpan.FromSeconds(5.0), Observable.Return(-1))
    select new { item, result };

var subscription =
    query
        .Subscribe(x =>
        {
            /* do something with `x.item` and/or `x.result` */
        });

这会自动遍历每个item并开始xmldiff.Compare的后台计算,但只允许每次计算在返回默认值{{1}之前花费5.0秒。 }}

-1变量是subscription,因此如果您想在完成之前中止整个IDisposable,只需致电query

答案 2 :(得分:0)

  

我跳过它并转到循环中的下一个项目

跳过"跳过它",你的意思是"把它留在那里"或者"取消它"?这两种情况完全不同。但对于这两个我建议您使用Task

//generate 10 example tasks
var tasks = Enumerable
    .Range(0, 10)
    .Select(n => new Task(() => DoSomething(n)))
    .ToList();

var maxExecutionTime = TimeSpan.FromSeconds(5);

foreach (var task in tasks)
{
    if (task.Wait(maxExecutionTime))
    {
        //the task is finished in time
    }
    else
    {
        // the task is over time
        // just leave it there
        // the loop continues
        // if you want to cancel it, see 
        // http://stackoverflow.com/questions/4783865/how-do-i-abort-cancel-tpl-tasks
    }
}

要改进的一件事是"你真的需要逐个完成你的任务吗?"如果它们是独立的,您可以并行运行它们。