在Office加载项中,我需要调用WPF,该WPF执行的功能可能会超时,但是我希望UI能够响应以允许用户单击“取消/关闭”按钮。 到目前为止,我的代码如下:
// From the Ribbon
var f = new Forms.CheckConnectivityPopup();
f.doneEvent.WaitOne();
// Get the status from the popup or null if the operation was cancelled
var status = f.status;
if(status != null)
// Continue the execution
--------------------------------
public partial class CheckConnectivityPopup : MetroWindow
{
public readonly BackgroundWorker worker = new BackgroundWorker();
public AutoResetEvent doneEvent = new AutoResetEvent(false);
public Status status = null;
public CheckConnectivityPopup()
{
InitializeComponent();
this.Show();
worker.DoWork += worker_DoWork;
worker.RunWorkerCompleted += worker_RunWorkerCompleted;
worker.RunWorkerAsync();
}
private void worker_DoWork(object sender, DoWorkEventArgs e)
{
// displayAndCheck();
status = CheckStatus();
Thread.Sleep(10000); // to simulate the time
}
private void worker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
doneEvent.Set();
this.Close();
}
}
到目前为止,弹出窗口一直处于冻结状态,直到睡眠期结束。
答案 0 :(得分:1)
WaitOne()
阻止当前线程。您可以将AutoResetEvent
替换为SemaphoreSlim
:
public partial class CheckConnectivityPopup : MetroWindow
{
public readonly BackgroundWorker worker = new BackgroundWorker();
public SemaphoreSlim doneEvent = new SemaphoreSlim(0, 1);
public Status status = null;
public CheckConnectivityPopup()
{
InitializeComponent();
this.Show();
worker.DoWork += worker_DoWork;
worker.RunWorkerCompleted += worker_RunWorkerCompleted;
worker.RunWorkerAsync();
}
private void worker_DoWork(object sender, DoWorkEventArgs e)
{
//displayAndCheck();
status = CheckStatus();
Thread.Sleep(10000); // to simulate the time
}
private void worker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
doneEvent.Release();
this.Close();
}
}
...您可以异步等待:
var f = new Forms.CheckConnectivityPopup();
await f.doneEvent.WaitAsync();
为使您能够等待WaitAsync()
方法,必须将创建CheckConnectivityPopup
实例的方法标记为async
:
void async YourMethod() { ... }
如果由于某种原因这不是一个选择,则可以改用ContinueWith
方法:
var f = new Forms.CheckConnectivityPopup();
f.doneEvent.WaitAsync().ContinueWith(_ =>
{
var status = f.status;
if (status != null)
{
//...
}
});