我们经常有这样的需求:如果一个方法的执行,超过了一个设定时间(timeout)就需要立即返回不再继续,这里我利用 C# 异步委托的 AsyncWaitHandle 来尽量简便的实现这一需求。
具体实现如下。注意,这里需要被调用的方法遵守 delegate TR TimeOutDelegate(T param); 形式的方法签名,如有其他需要,可以自行定制也很方便。
[csharp]
namespace TimeOutHelper
{
#region using directives
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Threading;
#endregion using directives
internal class Program
{
public delegate TR TimeOutDelegate<in T, out TR>(T param);
private static void Main()
{
Dictionary<Guid, string> result;
Console.WriteLine(TimeoutFunction.Execute(Test, "Hello, World!", out result, TimeSpan.FromSeconds(3)));
Console.WriteLine("Hello, World!");
Console.ReadKey();
}
public static Dictionary<Guid, string> Test(string sourceString)
{
var result = sourceString.ToDictionary(
character => Guid.NewGuid(),
character => character.ToString(CultureInfo.InvariantCulture));
Thread.Sleep(4000);
return result;
}
public static class TimeoutFunction
{
/// <summary>
/// Execute a method with timeout check
/// </summary>
/// <typeparam name="T">Target method parameter type</typeparam>
/// <typeparam name="TR">The result type of execution</typeparam>
/// <param name="timeoutMethod">Target method</param>
/// <param name="param">Target method parameter</param>
/// <param name="result">The result of execution</param>
/// <param name="timeout">Set timeout length</param>
/// <returns>Is timeout</returns>
public static Boolean Execute<T, TR>(
TimeOutDelegate<T, TR> timeoutMethod, T param, out TR result, TimeSpan timeout)
{
var asyncResult = timeoutMethod.BeginInvoke(param, null, null);
if (!asyncResult.AsyncWaitHandle.WaitOne(timeout, false))
{
result = default(TR);
return true;
}
result = timeoutMethod.EndInvoke(asyncResult);
return false;
}
}
}
}
[/csharp]