2009-06-19 4 views
4

Ich habe eine Methode implementiert mit der Event-based Asynchronous method pattern. Ich möchte auch eine synchrone Version dieser Methode anbieten, möchte sie aber nicht neu schreiben (da die Methode einen Aufruf von Silverlight an WCF erfordert, muss die Async-Version die primäre Methode sein).Ist diese Methode zum Konvertieren einer asynchronen Methode in eine synchrone Methode richtig?

Ich habe mit dem folgenden allgemeinen Verfahren kommen ein ereignisbasierte asynchrone Aufruf an einen Synchron ein konvertieren:

Func<TArg1, TArg2, TArg3, TEventArgs> 
    CreateSynchronousMethodFromAsync<TArg1, TArg2, TArg3, TEventArgs>(
     Action<TArg1, TArg2, TArg3, EventHandler<TEventArgs>> asyncMethod) 
     where TEventArgs : AsyncCompletedEventArgs 
    { 
     Func<TArg1, TArg2, TArg3, TEventArgs> syncMethod = (arg1, arg2, arg3) => 
     { 
      TEventArgs eventArgs = null; 

      using (var waitHandle = new ManualResetEvent(false)) 
      { 
       asyncMethod(arg1, arg2, arg3, (sender, e) => 
              { 
               eventArgs = e; 
               waitHandle.Set(); 
              }); 

       waitHandle.WaitOne(); 

       return eventArgs; 
      } 
     }; 

     return syncMethod; 
    } 

Also, wenn ich diese asynchrone Methode:

void ConnectAsync(string address, 
    string userName, 
    string password, 
    EventHandler<ConnectCompletedEventArgs> completionCallback) 

I kann es in einen synchronen Anruf wie folgt umwandeln:

public void Connect(string address, string userName, string password) 
{ 
    Func<string, string, string, ConnectCompletedEventArgs> connect = 
     CreateSynchronousMethodFromAsync<string, string, string, ConnectCompletedEventArgs>(ConnectAsync); 

    var connectResult = connect(address, userName, password); 

    if (connectResult.Error != null) 
    { 
     throw connectResult.Error; 
    } 
} 

Mein Anliegen ist über die uns e der eventArgs-Variable, die in der Schließung erfasst wird. Es wird in einem Thread festgelegt und von einem anderen abgerufen. Ist die Verwendung von ManualResetEvent ausreichend, um ein korrektes Lesen des Werts nach der Signalisierung des Ereignisses zu garantieren, oder muss ich etwas anderes tun?

Nun, Sie sind dabei, vielleicht möchten Sie hier einen Kommentar zum Umgang mit Ausnahmen abgeben. Mein Plan ist, dass die Async-Methode eine Ausnahmen, die unten in einer ConnectionException auftreten, umschlingt, oder etwas in der Art, so dass ich denke, dass das Auslösen der Ausnahme in diesem Fall korrekt ist.

Antwort

2

Basierend auf dem ASync-Muster, das auf der Seite besprochen wurde, auf die Sie verwiesen haben, sieht das wie ein ziemlich guter Versuch aus, den Async-Aufruf zu umbrechen.

Was mich jedoch zögern lässt, ist der Name der Methode 'BeginConnect'; Einige .NET-Klassen haben "BeginXxx"/"EndXxx" -Paare, um Async-Aufrufe zu verarbeiten, und diese geben normalerweise an, dass erfordert, dass der Aufruf 'EndXxx' vom Callback-Handler aufgerufen wird, was Ihr Schema nicht berücksichtigt zum.

Wenn der Anruf, den Sie umhüllen, tatsächlich mit dem auf der verknüpften Seite beschriebenen Muster übereinstimmt, sollte dies funktionieren, wenn der Anruf, den Sie umhüllen, einer der zweiten Art ist, sind Sie nicht ganz da ...

+0

Mein Code ist nur für die Verwendung mit Methoden vorgesehen, die dem Pattern Eventbased Asynchronous method entsprechen. Meine innere Methode BeginConnect, deren Implementierung ich nicht gezeigt habe, kümmert sich darum, die Begin/End-Aufrufe zu beenden. –

+0

Beachten Sie, dass Sie lieber als "throw connectionResult.Error" das als eine innere Ausnahme in eine neue Ausnahme umbrechen möchten, damit die Stapelüberwachung der ursprünglichen Ausnahme beibehalten wird. – jerryjvl

+2

@Sam: Ich würde empfehlen, die Methode basierend auf der Konvention in dem verknüpften Artikel zu benennen, um Verwirrung zu vermeiden ... machen Sie stattdessen 'ConnectAsync'. – jerryjvl

Verwandte Themen