2010-02-07 27 views
5

Ich habe in letzter Zeit eine Träne versucht zu lernen, alles was ich kann .Net Multithreading. (Es wird besser, aber ich habe immer noch das Gefühl, dass es viel zu lernen gibt). Im Moment habe ich auf dem APM (Asynchronous Programming Model) bin konzentriert, die gemeinhin als dies bekannt ist:Ist dies eine gute Möglichkeit, das asynchrone Programmiermodell zu implementieren?

//non async method 
public int DoSomeWork(int arg) 
{ 
    //do something and return result 
} 

//async version 
public IAsyncResult BeginDoSomeWork(int arg, AsyncCallback callback, object @object) 
{ 

} 

public int EndDoSomeWork(IAsyncResult result) 
{ 

} 

Nun lassen Sie uns sagen, dass ich einige Bibliothek ich schreibe, und ich möchte diese Funktionalität jemand belichten, wer raubend Meine API, ich habe über Möglichkeiten nachgedacht, dieses Muster zu implementieren. Das Implementieren der IAsyncResult-Schnittstelle ist eine Möglichkeit, aber es scheint ziemlich komplex zu sein. Meine Frage ist, ob die Verwendung von Delegaten eine akzeptable Lösung ist. Was ich damit meine, ist dies:

public class MyClass 
{ 
    private Func<int, int> func; 

    //non async method 
    public int DoSomeWork(int arg) 
    { 
     //do something and return result 
    } 

    //async version 
    public IAsyncResult BeginDoSomeWork(int arg, AsyncCallback callback, object @object) 
    { 
     this.func = new Func<int, int>(DoSomeWork); 
     var asyncResult = this.func.BeginInvoke(arg,callback,object); 
     return asyncResult; 
    } 

    public int EndDoSomeWork(IAsyncResult result) 
    { 
     return this.func.EndInvoke(result); 
    } 
} 

Grundsätzlich alle Delegierten die BeginXXX und EndXxx Funktionalität direkt hinein gebacken hat. Ist es in Ordnung, das auszunutzen und das IAsyncResult bloßzustellen, oder ist da etwas nicht in Ordnung mit dem ich nicht denke?

Antwort

1

Ich denke, das ist ein guter Weg, um die APM, aber im Moment implementieren werden Sie einen Fehler mit mehr als einem asynchronen Aufruf pro Instanz erhalten.

Warum externalisieren Sie nicht nur die Delegierten Nutzung?

Was ich meine ist, als wenn Sie nur die eigentliche Logik in Ihrer Klasse setzen, aber dann jemand lassen, die Ihre Methode aufruft tun:

MyClass c = new MyClass(); 
Func<int, int> f = c.DoSomeWork; 
IAsyncResult ar1 = f.BeginInvoke(1, null, null); 
IAsyncResult ar2 = f.BeginInvoke(2, null, null); 
//... 

Ich denke, was ich bin nicht dafür, auch die Umsetzung APM selbst, aber ich empfehle allen, die Ihre Methode aufrufen, dass sie den APM verwenden, der in Delegaten integriert ist.

0

IMHO, ich glaube nicht, Ihre Asynchron-Methode einen Wert hinzufügen, so lassen Sie den Client entscheiden, ob es Ihre Methode asynchron aufrufen wird.

+0

Es war nur ein Beispiel. Ignoriere die tatsächliche Implementierung (die zugegebenermaßen dumm und sinnlos aussieht), ich frage nach der Verwendung des Delegaten und es ist IAsyncResult. – BFree

+0

Da sowohl eine synchrone als auch eine asynchrone Version bereitgestellt wird, muss der Client diese Entscheidung dennoch treffen. Das OP ist mehr darüber besorgt, ob die gewählte Methode ein guter Weg zur Implementierung von APM ist oder nicht. – Crippledsmurf

+0

@BFree, ich c jetzt. – Benny

0

Ich denke, es ist eine sehr gültige Übung, wenn nichts anderes. Ich arbeite auch an einem asynchronen 'Delegate'-Handler. Sie können die Flexibilität erhöhen, und Sie werden eine Menge über das asynchrone Modell lernen.

Ich weiß, das SO question einige Linq Übung darin enthält. Es könnte Ihnen jedoch eine Idee geben, wie Sie Ausdrucksbäume verwenden können, um es etwas robuster zu machen. Ich muss noch in das Thema eintauchen und Ihnen konkretere Informationen geben. Hier

ist ein Beispiel für ein Stück meines alten Code auf asynchrone Methoden veröffentlichen. Dies ist eine datierte Übung in Lernreflexion und einige interessante Implementierungen. Nehmen Sie es für das, was es wert ist, aber es könnte Ihnen einige Ideen helfen:

public delegate void delVoidMethod(params object[] args); 

/// <summary> 
/// Publishes an asynchronous method to the delegate collection. 
/// </summary> 
/// <param name="methodOwner">Target object owning the delegated method.</param> 
/// <param name="method">The delegated method.</param> 
/// <param name="callback">The method designated as a callback delegate.</param> 
/// <param name="ptr">The delegated method's runtime handle.</param> 
/// <returns>True if publishing was successful.</returns> 
public bool PublishAsyncMethod(object target , MethodInfo method , 
    MethodInfo callback , out IntPtr ptr) 
{ 
    try 
    { 
     ptr = method.MethodHandle.Value; 

     delVoidMethod dMethod = (delVoidMethod)Delegate.CreateDelegate 
      (typeof(delVoidMethod) , target , method); 
     AsyncCallback callBack = (AsyncCallback)Delegate.CreateDelegate 
      (typeof(AsyncCallback) , target , callback); 

     handlers[ptr] = new DelegateStruct(dMethod , callBack); 

     Logger.WriteLine("Delegate : {0}.{1} -> {2}.{3} published." , 
      method.DeclaringType.Name , method.Name , 
      callback.DeclaringType.Name , callback.Name); 
     return true; 
    } 
    catch (ArgumentException ArgEx) 
    { 
     Logger.Write(DH_ERROR , ERR_MSG , 
      ArgEx.Source , ArgEx.InnerException , ArgEx.Message); 
    } 
    catch (MissingMethodException BadMethEx) 
    { 
     Logger.Write(DH_ERROR , ERR_MSG , 
      BadMethEx.Source , BadMethEx.InnerException , BadMethEx.Message); 
    } 
    catch (MethodAccessException MethAccEx) 
    { 
     Logger.Write(DH_ERROR , ERR_MSG , 
      MethAccEx.Source , MethAccEx.InnerException , MethAccEx.Message); 
    } 

    ptr = IntPtr.Zero; 

    return false; 
} 
0

Absolut nichts falsch, aber es scheint ein bisschen sinnlos.

Sie die Umsetzung im Wesentlichen die Facade pattern, aber nicht machen die Schnittstelle Einfacher. Je nach spezifischer Situation kann es sinnvoller sein, eigene Klassen hinzuzufügen, um die Verwendung von AsyncCallback und IAsyncResult zu vereinfachen, damit die Aufrufe die in Ihren Klassen verwendeten Eigenschaften genauer widerspiegeln.

+0

Ich sehe nicht die Ähnlichkeiten in was das OP tut im Vergleich zu den Kugeln, die das Fassadenmuster definieren. – IAbstract

0

Ich persönlich bevorzuge die Verwendung eines Ereignisses zu benachrichtigen, wenn der asynchrone Prozess endet, wenn die Klasse von einer anderen Bibliothek verwendet werden soll. Verwenden Sie die AsyncOperation-Klasse und den SendOrPostCallback-Delegaten, um sicherzustellen, dass die Ereignisse im Anruferthread ausgelöst werden stören Sie die Benutzeroberfläche. Wenn jedoch die asynchrone Operation in derselben Assembly ausgeführt werden soll, bevorzuge ich lieber den aufrufenden Code, um zu definieren, wie der asynchrone Aufruf ausgeführt wird.

Verwandte Themen