WPF неблокирующий пользовательский интерфейс - PullRequest
0 голосов
/ 10 марта 2019

В надстройке Office мне нужно вызвать WPF, который выполняет функцию, которая может истечь, но я хочу, чтобы пользовательский интерфейс реагировал, чтобы пользователь мог нажать кнопку «Отмена / Закрыть». Пока мой код выглядит следующим образом:

// 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();
    }
}

Пока всплывающее окно заморожено, пока не завершится период ожидания.

1 Ответ

1 голос
/ 11 марта 2019

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)
    {
        //...
    }
});
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...