处理任务超时和异常

Handling task timeout and exception

我在 WPF 应用程序中使用 C# (.NET Framework 4.8) 中的某个 Func<bool> func 并希望执行它。我想要一种采用这种 Funcs 和 return 布尔值的方法。

  1. 它应该 运行 在后台并且不会阻塞 UI 线程。可能我需要 Task<bool> 吗?
  2. 如果超过某个超时限制,应该取消并且return false.
  3. 程序应该等待任务完成但不会如果它已经提前完成则等待完整的时间限制。
  4. 如果它运行出错,应该打印错误消息,应该取消任务并且程序应该不会崩溃或冻结。

是否有任何复杂的方法可以满足这些要求? 如果这是更好的解决方案,该解决方案也可以使用 Task<bool> 而不是 Func<bool>。 它应该可以像这样使用:

public class Program
{
    public static void Main(string[] args)
    {
        bool result = ExecuteFuncWithTimeLimit(3000, () =>
        {
            // some code here of a specific task / function
        });
    }

    public static bool ExecuteFuncWithTimeLimit(int timeLimit_milliseconds, Func<bool> codeBlock)
    {
        // run func/task in background so GUI is not freezed
        // if completed in time: return result of codeBlock
        // if calceled due to time limit: return false
        // if error occured: print error message and return false
    }
}

经过一段时间的试验,我找到了一个通过中止线程的解决方案。我知道不推荐它,但它工作正常并且对我有用。

public class Program
{
    public static void Main(string[] args)
    {
        Task.Run(() =>
        {
            if (!ExecuteTaskWithTimeLimit(1000, () => { return DoStuff1(); })) return;
            if (!ExecuteTaskWithTimeLimit(1000, () => { return DoStuff2(); })) return;
            // ...
        });
    }

    public static bool ExecuteTaskWithTimeLimit(int timeLimit_milliseconds, Func<bool> codeBlock)
    {
        Thread thread = null;
        Exception exception = null;

        // do work
        Task<bool> task = Task<bool>.Factory.StartNew(() =>
        {
            thread = Thread.CurrentThread;
            try
            {
                return codeBlock();
            }
            catch (Exception e)
            {
                exception = e;
                return false;
            }
        });

        // wait for the task to complete or the maximum allowed time
        task.Wait(timeLimit_milliseconds);

        // if task is canceled: show message and return false
        if (!task.IsCompleted && thread != null && thread.IsAlive)
        {
            ConsoleWriteLine("Task cancled because it timed out after " + timeLimit_milliseconds + "ms.");
            thread.Abort();
            return false;
        }

        // if error occured: show message and return false
        if (exception != null)
        {
            MessageBox.Show(exception.Message, "Exeption", MessageBoxButton.OK, MessageBoxImage.Error);
            return false;
        }

        // if task has no error and is not canceled: return its return value
        return task.Result;
    }
}