2015-03-17 14 views
14

Ich versuche einen Code zu schreiben, der ausgeführt wird, wenn eine Bedingung erfüllt ist. Momentan verwende ich while ... Schleife, von der ich weiß, dass sie nicht sehr effizient ist. Ich schaue auch auf AutoResetEvent(), aber ich weiß nicht, wie man es so implementiert, dass es überprüft, bis die Bedingung wahr ist.C# Warte, bis die Bedingung wahr ist

Der Code passiert auch innerhalb einer asynchronen Methode zu leben, so könnte eine Art warten könnte funktionieren?

private async void btnOk_Click(object sender, EventArgs e) 
{ 
     // Do some work 
     Task<string> task = Task.Run(() => GreatBigMethod()); 
     string GreatBigMethod = await task; 

     // Wait until condition is false 
     while (!isExcelInteractive()) 
     { 
      Console.WriteLine("Excel is busy"); 
     } 

     // Do work 
     Console.WriteLine("YAY"); 
} 


    private bool isExcelInteractive() 
    { 
     try 
     { 
      Globals.ThisWorkbook.Application.Interactive = Globals.ThisWorkbook.Application.Interactive; 
      return true; // Excel is free 
     } 
     catch 
     { 
      return false; // Excel will throw an exception, meaning its busy 
     } 
    } 

Ich muss einen Weg finden, ohne in einer Schleife stecken CPU Überprüfung isExcelInteractive() zu halten.

Hinweis: In Excel gibt es keinen Event-Handler, der ausgelöst würde, wenn er sich nicht im Bearbeitungsmodus befindet.

+1

Wer ändert isExcelInteractive Wert? – Peyman

+0

'isExcelInteractive()' ist eine Methode, um zu überprüfen, ob Excel beschäftigt ist. Es wird True zurückgegeben, wenn Excel nicht im Bearbeitungsmodus ist. Es ist etwas, was ich überprüfen muss, bis es wahr ist, und es gibt keine Event-Handler für diese – Keylee

+0

Ich denke, Sie brauchen hier keine async-Methode, haben Sie meine Antwort überprüft? – Peyman

Antwort

15

Zumindest können Sie Ihre Schleife von einer "busy-wait" zu einer langsamen Umfrage ändern. Beispiel:

while (!isExcelInteractive()) 
    { 
     Console.WriteLine("Excel is busy"); 
     await Task.Delay(25); 
    } 
+0

Ich habe darüber nachgedacht. Ist das eine gängige Praxis? Ich bin noch sehr neu im Programmieren. – Keylee

+0

Ich habe dies mit einer Verzögerung von 1000 ms implementiert. Vielen Dank. – Keylee

6

können Sie verwenden thread waiting handler

private readonly System.Threading.EventWaitHandle waitHandle = new System.Threading.AutoResetEvent(false); 
private void btnOk_Click(object sender, EventArgs e) 
{ 
    // Do some work 
    Task<string> task = Task.Run(() => GreatBigMethod()); 
    string GreatBigMethod = await task; 

    // Wait until condition is false 
    waitHandle.WaitOne(); 
    Console.WriteLine("Excel is busy"); 
    waitHandle.Reset(); 

    // Do work 
    Console.WriteLine("YAY"); 
} 

dann einige andere Job Handler

void isExcelInteractive() 
{ 
    /// Do your check 
    waitHandle.Set() 
} 

-Update festlegen müssen: Wenn Sie diese Lösung verwenden möchten, müssen Sie isExcelInteractive() kontinuierlich nennen mit spezifisches Intervall:

var actions = new []{isExcelInteractive,() => Thread.Sleep(25)}; 
foreach (var action in actions) 
{          
    action(); 
} 
+0

Ist es deine Antwort? Ob isExcelInteractive Zugriff auf waitHandle, wenn Sie dieses Objekt nicht zwischen beiden Methoden teilen müssen – Peyman

+0

Ich bin mir nicht sicher, ob diese Antwort funktionieren würde. Was heißt 'isExcelInteractive()'? Dies scheint nicht zu überprüfen 'isExcelInteractive()' kontinuierlich – Keylee

+0

, so müssen Sie @Ben Lösung verwenden, oder Aufruf isExcelInteractive() -Methode mit bestimmten Intervall – Peyman

-1

Sie können ein asynchrones Ergebnis und einen Delegaten dafür verwenden. Wenn Sie auf the documentation nachlesen, sollte es ziemlich klar machen, was zu tun ist. Ich kann einen Beispielcode schreiben, wenn Sie möchten, und an diese Antwort anhängen.

Action isExcelInteractive = IsExcelInteractive; 

private async void btnOk_Click(object sender, EventArgs e) 
{ 
    IAsyncResult result = isExcelInteractive.BeginInvoke(ItIsDone, null); 
    result.AsyncWaitHandle.WaitOne(); 
    Console.WriteLine("YAY"); 
} 

static void IsExcelInteractive(){ 
    while (something_is_false) // do your check here 
    { 
     if(something_is_true) 
      return true; 
    } 
    Thread.Sleep(1); 
} 

void ItIsDone(IAsyncResult result) 
{ 
    this.isExcelInteractive.EndInvoke(result); 
} 

Entschuldigt, wenn dieser Code nicht zu 100% abgeschlossen ist, habe ich nicht Visual Studio auf diesem Computer, aber hoffentlich wird es Sie, wo Sie bekommen müssen.

+0

Bitte mach das, damit ich schneller verstehe :) – Keylee

Verwandte Themen