GUI обновляется только после завершения рабочего потока - PullRequest
0 голосов
/ 10 сентября 2018

У меня есть приложение Windows Form и управляемая DLL в одном решении. DLL содержит некоторые трудоемкие функции, во время которых я хочу обновить содержимое формы (обратный вызов из DLL в форму с обновлениями progess). У меня есть следующий код:

Код формы, где я инициализирую DLL и предоставляю ей функцию обратного вызова в методе Initialize. Я также запускаю отдельный поток для периодической проверки message_queue на наличие новых сообщений из DLL. Функция DLL также вызывается в отдельном потоке (без блокировки для пользовательского интерфейса).

private LibraryDLL library_dll;
private ConcurrentQueue<string> message_queue;

public MainForm()
{
    InitializeComponent();
    library_dll = new LibraryDLL();
    message_queue = new ConcurrentQueue<string>();
    library_dll.Initialize(ProcessMessage);

    new Thread(() =>
    {
        Thread.CurrentThread.IsBackground = true;
        string message;
        if (message_queue.TryDequeue(out message))
        {
            PrintMessage(message);
        }
    }).Start();
}

private void ProcessMessage(string message)
{
    message_queue.Enqueue(message);
}

private void PrintMessage(string message)
{
    this.Invoke((MethodInvoker)delegate
    {
        listBox_rows.Items.Add(message);
    });            
}

private void button_send_Click(object sender, EventArgs e)
{
    new Thread(() =>
    {
        Thread.CurrentThread.IsBackground = true; 
        library_dll.DoWork();           
    }).Start();
}

В коде DLL я использую метод обратного вызова, чтобы сообщить о прогрессе:

private CallBack callback;
public delegate void CallBack(string message);

public LibraryDLL() { }

public void Initialize(CallBack callback)
{
    this.callback = callback;
}

public void DoWork()
{
    callback("working...")
    Thread.Sleep(500);
    callback("working...")
    Thread.Sleep(500);
    callback("working...")
    Thread.Sleep(500);
}

Моя проблема в том, что вместо строки «работающая», появляющейся каждые 500 мс, она появляется 3 раза после 1500 мс (только после завершения потока, в котором выполняется метод DoWork). Я также попытался использовать последовательность Invalidate () - Update () - Refresh () в функции PrintMessage формы, но без какого-либо эффекта.

Спасибо за совет!

EDIT1:

Я изменил код для использования BackgroundWorker, однако проблема остается (не более 1500 мс, чем все 3 строки одновременно).

BackgroundWorker bck_worker;

public MainForm()
{
    InitializeComponent();
    library_dll = new LibraryDLL();
    library_dll.Initialize(bck_worker);

    bck_worker = new BackgroundWorker();
    bck_worker.ProgressChanged += new ProgressChangedEventHandler(bckWorker_ProgressChanged);
    bck_worker.WorkerReportsProgress = true;
    bck_worker.WorkerSupportsCancellation = true;
} 

private void bckWorker_DoWork(object sender, DoWorkEventArgs e)
{
    library_dll.DoWork();
}

private void bckWorker_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
    PrintMessage((string)e.UserState);
}

private void button_send_Click(object sender, EventArgs e)
{
    bck_worker.DoWork += new DoWorkEventHandler(bckWorker_DoWork);
    bck_worker.RunWorkerAsync();
}

private void PrintMessage(string message)
{
    listBox_rows.Items.Add(message);
}

И DLL:

private BackgroundWorker bck_worker;

public LibraryDLL() { }

public void Initialize(BackgroundWorker bck_worker)
{
    this.bck_worker = bck_worker;
}

public void DoWork()
{
    bck_worker.ReportProgress(25, "working...");        
    Thread.Sleep(500);
    bck_worker.ReportProgress(50, "working...");
    Thread.Sleep(500);
    bck_worker.ReportProgress(75, "working...");
    Thread.Sleep(500);
}

EDIT2:

ОК, теперь я попытался добавить последовательность Invalidate-Update-Refresh в конце функции PrintMessage, и она наконец работает (с подходом BackgroundWorker)!

1 Ответ

0 голосов
/ 10 сентября 2018

Использование фонового рабочего и отчета о работниках для обновления вашего пользовательского интерфейса: фоновый рабочий документ

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...