У меня есть приложение 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)!