简体   繁体   English

仅在辅助线程结束后才更新GUI

[英]GUI updates only after the worker thread has ended

I have a Windows Form application and managed DLL in one solution. 我在一个解决方案中有一个Windows Form应用程序和托管DLL。 DLL contains some time consuming functions during which I wish to update the Form contents (callback from the DLL to the Form with progess updates). DLL包含一些耗时的函数,在这些函数中,我希望更新表单内容(使用动态更新从DLL回调到Form)。 I have the following code: 我有以下代码:

Form code, where I initialize the DLL and give it a callback function in the Initialize method. 表单代码,我在其中初始化DLL,并在Initialize方法中为其提供回调函数。 I also start a separate Thread to periodicly check the message_queue for new messages from the DLL. 我还启动了一个单独的线程来定期检查message_queue中是否有来自DLL的新消息。 The DLL function is also called in a separate Thread (non blocking for the UI). DLL函数也可以在单独的线程中调用(UI不阻塞)。

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

In DLL code, I use the callback method to report progress: 在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);
}

My problem is, that instead of string "working" appearing every 500ms, it appears 3 times after 1500ms (only after the Thread in which the DoWork method is running ends). 我的问题是,而不是字符串“ working”每500毫秒出现一次,而是在1500毫秒之后出现3次(仅在运行DoWork方法的线程结束之后)。 I also tried the Invalidate()-Update()-Refresh() sequence in the Form's PrintMessage function, but without any effect. 我还尝试了窗体的PrintMessage函数中的Invalidate()-Update()-Refresh()序列,但没有任何效果。

Thanks for the advice! 谢谢你的建议!

EDIT1: 编辑1:

I modified the code to use the BackgroundWorker, however, the problem remains (nothing for 1500ms, than all 3 strings at once). 我修改了代码以使用BackgroundWorker,但是问题仍然存在(1500ms内无任何问题,一次只剩下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);
}

And the DLL: 和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: 编辑2:

OK, I now tried to add the Invalidate-Update-Refresh sequence at the end of the PrintMessage function and it finaly works (with the BackgroundWorker approach)! 好的,我现在尝试在PrintMessage函数的末尾添加Invalidate-Update-Refresh序列,并且该序列最终可以工作(使用BackgroundWorker方法)!

使用后台工作人员和工作人员的报告进度来更新您的UI: 后台工作人员doc

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 使用后台工作程序有效地写入GUI线程 - Using a background worker to efficiently write to a GUI thread 工作者线程可以在GUI中读取控件吗? - can a worker thread read a control in the GUI? 从线程加速实时Gui更新 - Speeding up realtime Gui updates from a thread 后台工作程序+套接字中的C#进度栏-进度栏仅在套接字通讯完成后才更新 - C# Progress Bar in background worker + Socket - Progress bar only updates after socket comm is done 仅在主线程执行完成后,后台工作线程中的函数调用才会执行? - function call in background worker thread get executed only after main thread execution complete? 如何从工作线程/类更新GUI线程/类? - How to update GUI thread/class from worker thread/class? ReadKey 在线程超时结束之前获取字符 - ReadKey getting characters pressed before a thread timeout has ended C# 更新 DatagridView(格式) 从工作线程更新 - C# Update DatagridView (format) Updates from worker thread 使用分派器从工作线程修改GUI元素的正确方法? - Correct approach to modifying GUI elements from a worker thread with the Dispatcher? 为什么统一相机滚动仅在过渡完成后才更新场景? - why unity camera scrolling updates scene only after transition has finished?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM