2011-01-21 3 views
0

私はMVPのようなアプリケーションを持っていますが、すべての高価な操作で非同期呼び出しが使用されています。UIスレッドをブロックせずに保留中の操作が完了するまで待つ

例:データ入力フォームで[保存]をクリックすると非同期操作が行われ、終了するとUIスレッドをブロックせずに画面を編集可能なフォームに復元します(つまり、アプリケーション内の他の表示ウィンドウをブロックしません) 。

すべてがここで正常に動作しますが、次のシナリオを与えられた:

ユーザーがフォームを閉じようとすると、彼は彼がすることを好む場合は、彼が閉じるように起こっていることを確認している場合、ユーザーに尋ねる確認メッセージを取得します閉じる前に保存してください。 ユーザーが「保存」をクリックすると前に説明したのと同じロジックが実行されますが、この呼び出しがUIスレッドで完了するのを待たされます(非同期呼び出しなどのエラーがある場合) UIスレッドをブロックすることなく、他の方法で行う方法はありません。

提案がありますか?ありがとう!

---編集---- 私が今やっていることは、このループをプレゼンターにすべての私のWaitHandlesに待っている:

while (!WaitHandles.All(h => h.WaitOne(1))) 
    Application.DoEvents(); 

それは少し汚れを感じている..しかし、少なくとも、スレッドをブロックしないことをシミュレートします。これは、何らかの理由で私がやってはならないことですか?

+0

*エラーがある場合はUIスレッドで待たされます*と* UIスレッドをブロックせずにどうすればいいですか?*これら2つのステートメントは矛盾しています。操作が完了するまでウインドウを隠してから終了したり、エラーを処理したりすることができますか? – Tergiver

+0

理想的には、UIスレッド以外のどこかで待っていますか?他の声明ほど矛盾しています。今更新してみよう –

+0

私は、同じページにいることを確認するために質問を理解することができます。私のアプリケーションは死にそうですが、非同期操作が完了するまでには完了する必要があります。ブロックせずにどうすればいいですか? UIスレッドはユーザーの視点から見て死んでいます(終了しています)、ブロックされているかどうかはどのような違いがありますか? – Tergiver

答えて

0

「hideメソッド」の例を次に示します。確かに、それはMVPではなく、単なる例です。

using System; 
using System.ComponentModel; 
using System.Diagnostics; 
using System.Drawing; 
using System.Threading; 
using System.Windows.Forms; 

class Form1 : Form 
{ 
    [STAThread] 
    static void Main() 
    { 
     Application.EnableVisualStyles(); 
     Application.SetCompatibleTextRenderingDefault(false); 
     Application.Run(new Form1()); 
    } 

    public Form1() 
    { 
     Text = "First Form"; 
     Button button; 
     Controls.Add(button = new Button { Text = "Launch 2nd Form", AutoSize = true, Location = new Point(10, 10) }); 
     button.Click += (s, e) => new Form2 { StartPosition = FormStartPosition.Manual, Location = new Point(Right, Top) }.Show(this); 
    } 
} 

class Form2 : Form 
{ 
    public Form2() 
    { 
     Text = "Second Form"; 
     dirty = true; 
    } 

    private bool dirty; 

    protected override void OnClosing(CancelEventArgs e) 
    { 
     DialogResult result; 
     if (dirty && (result = new ConfirmSaveForm().ShowDialog(this)) != DialogResult.No) 
     { 
      if (Owner != null) 
       Owner.Activate(); 
      Hide(); 
      e.Cancel = true; 
      SaveAsync(result == DialogResult.Cancel); 
     } 
     base.OnClosing(e); 
    } 

    protected override void OnClosed(EventArgs e) 
    { 
     Trace.WriteLine("Second Form Closed"); 
     base.OnClosed(e); 
    } 

    private void SaveAsync(bool fail) 
    { 
     SaveAsyncBegin(); 
     var sad = new Action<bool>(PerformAsyncSave); 
     sad.BeginInvoke(fail, (ar) => 
     { 
      try { sad.EndInvoke(ar); } 
      catch (Exception ex) { Invoke(new Action<Exception>(SaveAsyncException), ex); return; } 
      Invoke(new Action(SaveAsyncEnd)); 
     }, null); 
    } 

    private void SaveAsyncBegin() 
    { 
     // Update UI for save 
    } 

    private void PerformAsyncSave(bool fail) 
    { 
     Trace.WriteLine("Begin Saving"); 
     Thread.Sleep(1000); // Do some work 
     if (fail) 
     { 
      Trace.WriteLine("Failing Save"); 
      throw new Exception("Save Failed"); 
     } 
     dirty = false; 
    } 

    private void SaveAsyncEnd() 
    { 
     Trace.WriteLine("Save Succeeded"); 
     Close(); 
    } 

    private void SaveAsyncException(Exception ex) 
    { 
     Trace.WriteLine("Save Failed"); 
     Show(); 
     MessageBox.Show(this, ex.Message, "Save Failed", MessageBoxButtons.OK, MessageBoxIcon.Stop); 
    } 
} 

class ConfirmSaveForm : Form 
{ 
    public ConfirmSaveForm() 
    { 
     Text = "Confirm Save"; 
     FormBorderStyle = FormBorderStyle.FixedDialog; 
     ControlBox = false; 
     ClientSize = new Size(480, 50); 
     StartPosition = FormStartPosition.CenterParent; 
     Controls.Add(new Button { Text = "Yes, Fail", DialogResult = DialogResult.Cancel, Size = new Size(150, 30), Location = new Point(10, 10) }); 
     Controls.Add(new Button { Text = "Yes, Succeed", DialogResult = DialogResult.Yes, Size = new Size(150, 30), Location = new Point(160, 10) }); 
     Controls.Add(new Button { Text = "No", DialogResult = DialogResult.No, Size = new Size(150, 30), Location = new Point(320, 10) }); 
     AcceptButton = Controls[0] as IButtonControl; 
    } 
} 
関連する問題