是否可以在单个方法中隐藏回调机制?

时间:2012-03-22 13:31:47

标签: c# .net events event-handling

我有这样的界面:

interface IAuthentication
{
    void AuthenticateAsync(string user, string pwhash);
    event EventHandler<AuthenticationResult> AuthenticationDone;
}

这可以通过在事件完成时引发事件来起作用。现在,我想将这个机制包装在一个阻塞方法中,该方法在完成后返回验证结果:

AuthenticationResult Authenticate(string user, string pwhash)
{
    var auth = GetIAuthenticator();
    // ... do something
    return <the authentication result from the even argument>;
}

这有可能吗?

3 个答案:

答案 0 :(得分:3)

使用等待句柄,您不需要检查一些标志,阻止线程和设置超时:

private AuthenticationResult Authenticate(string user, string pwhash)
{            
    IAuthentication auth = GetIAuthenticator();
    AuthenticationResult result = null;
    AutoResetEvent waitHangle = new AutoResetEvent(false);

    auth.AuthenticationDone += (o, e) =>
        {
            result = e;
            waitHangle.Set();
        };

    auth.AuthenticateAsync(user, pwhash);
    waitHangle.WaitOne(); // or waitHangle.WaitOne(interval);
    return result;
}

答案 1 :(得分:2)

private AuthenticationResult Authenticate(string user, string pwhash)
{
    bool isDone = false;
    AuthenticationResult results = null
    var auth = GetIAuthenticator(); 
    auth.AuthenticationDone += (o, e) => 
    {
        isDone = true;
        results = e;
    };

    auth.AuthenticateAsync(user, pwhash);

    long maxWaitTimeSeconds = 10;
    long thresholdMilliseconds = 100;
    int countToWait = maxWaitTimeSeconds * 1000 / thresholdMilliseconds;
    while (!isDone || countToWait-- > 0)
    {
       Thread.Sleep(thresholdMilliseconds);
    }

    if (countToWait == 0 && !isDone)
    {
       // TODO: timeout handling
    }

    return results;    
}

PS: 如果event args永远不能为null - 你可以删除isDone变量,只需使用result != null作为“身份验证完成”指标

答案 2 :(得分:2)

当您使用.Net 4.0时,您可以利用任务并行库。

这是一个非常基本的程序,展示了如何使用TaskCompletionSource

public class Test
{
    public void Go()
    {
        ThreadPool.QueueUserWorkItem((z) => this.Imp());
    }

    private void Imp()
    {
        Console.WriteLine("Asynchronous operation in progress (1/2)...");
        Thread.Sleep(2000);
        Console.WriteLine("Asynchronous operation in progress (2/2)...");

        if (this.Done != null)
        {
            this.Done(this, EventArgs.Empty);
        }
    }

    public event EventHandler Done;
}

internal class Program
{
    private static void Main(string[] args)
    {
        Test test = new Test();

        TaskCompletionSource<object> tcs = new TaskCompletionSource<object>(null);

        Console.WriteLine("Starting asynchronous operation");

        Task.Factory.StartNew(() =>
        {
            test.Done += (sender, e) => tcs.SetResult(null);
            test.Go();
        });

        // Blocking until completion of the async operation
        var tmp = tcs.Task.Result;

        Console.WriteLine("Asynchronous operation completed");

        Console.ReadKey();
    }
}

结果是:

Starting asynchronous operation
Asynchronous operation in progress (1/2)...
Asynchronous operation in progress (2/2)...
Asynchronous operation completed

如您所见,执行流程将被阻止,直到异步操作终止。