简体   繁体   中英

Handling task timeout and exception

I have a certain Func<bool> func in C# (.NET Framework 4.8) in a WPF application and want it to be executed. I'd like to have a method that takes this kind of Funcs and returns a bool.

  1. It should run in the background and not block the UI thread. Probably I need Task<bool> for that?
  2. If it takes longer than a certain timeout limit, it should be canceled and return false .
  3. The program should wait for the task to be completed but not wait for the full time limit if it is already finished earlier.
  4. If it runs into an error, error message should be printed, the task should be canceled and the program should not crash or freeze.

Is there any sophisticated method that fullfills these requirements? The solution can also use Task<bool> instead of Func<bool> if this a better solution. It should be usable in a way similar to this:

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
    }
}

After a time of experimenting I found a solution via aborting threads. I know its not recommended, but it works fine and does its job for me.

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;
    }
}

1: yes you need asynchronus because you want to avoid freez ui maybe use Task you can checked timeer by a feild start and end of method and use try-cache for avoid crash you can check time in catch block and print message and you can call method for canceling program after that use continue key word in catch block.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM