Hier ist der Code:IAsyncResult.AsyncWaitHandle.WaitOne() vervollständigt vor Rückruf
class LongOp
{
//The delegate
Action longOpDelegate = LongOp.DoLongOp;
//The result
string longOpResult = null;
//The Main Method
public string CallLongOp()
{
//Call the asynchronous operation
IAsyncResult result = longOpDelegate.BeginInvoke(Callback, null);
//Wait for it to complete
result.AsyncWaitHandle.WaitOne();
//return result saved in Callback
return longOpResult;
}
//The long operation
static void DoLongOp()
{
Thread.Sleep(5000);
}
//The Callback
void Callback(IAsyncResult result)
{
longOpResult = "Completed";
this.longOpDelegate.EndInvoke(result);
}
}
Hier ist der Testfall:
[TestMethod]
public void TestBeginInvoke()
{
var longOp = new LongOp();
var result = longOp.CallLongOp();
//This can fail
Assert.IsNotNull(result);
}
Wenn dies der Testfall versagen kann ausgeführt wird. Warum genau?
Es gibt sehr wenig Dokumentation darüber, wie delegate.BeginInvoke funktioniert. Hat jemand irgendwelche Einsichten, die sie teilen möchten?
Aktualisieren Dies ist eine subtile Race-Bedingung, die in MSDN oder anderswo nicht gut dokumentiert ist. Das Problem, wie in der akzeptierten Antwort erklärt, ist, dass, wenn die Operation abgeschlossen ist, der Wait-Handle signalisiert wird, und dann der Callback ausgeführt wird. Das Signal gibt den wartenden Haupt-Thread frei und nun tritt die Callback-Ausführung in das "Rennen" ein. Jeffry Richter's suggested implementation zeigt, was hinter den Kulissen passiert:
// If the event exists, set it
if (m_AsyncWaitHandle != null) m_AsyncWaitHandle.Set();
// If a callback method was set, call it
if (m_AsyncCallback != null) m_AsyncCallback(this);
Für eine Lösung zu Ben Voigt Antwort verweisen. Diese Implementierung verursacht nicht den zusätzlichen Aufwand eines zweiten Warte-Handle.
Entfernen Sie den Rückruf und versuchen Sie es erneut. – jgauffin
@jgauffin, wenn Sie bemerken, dass die Frage nicht "Wie bekomme ich das zur Arbeit?" Dies ist eindeutig ein konstruiertes Beispiel. –
Ihre Frage ist: "Wenn dies ausgeführt wird, kann der Testfall fehlschlagen. Warum genau?". Ich habe * das * beantwortet. Weil Sie versuchen, zwei sehr unterschiedliche Arten der Handhabung einer asynchronen Operation zu mischen. – jgauffin