通过调用从后台线程C#线程问题 [英] c# Thread issue using Invoke from a background thread

查看:196
本文介绍了通过调用从后台线程C#线程问题的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有线程,它处理一些分析工作。

 私有静态无效ThreadProc的(obj对象)
    {
        VAR电网=(DataGridView的)目标文件;
        的foreach(的DataGridViewRow行grid.Rows)
        {
            如果(Parser.Get preparationByClientNameForSynonims(row.Cells [$ P $页。Value.ToString())!= NULL)
                UpdateGridSafe(网格,row.Index,1);
            Thread.sleep代码(10);
        }
    }
 

我要安全地更新我的GridView的循环,所以我用经典的方式:

 私人委托无效UpdateGridDelegate(DataGridView的网格,诠释rowIdx,int型的);
    公共静态无效UpdateGridSafe(DataGridView的网格,诠释rowIdx,整型)
    {
        如果(grid.InvokeRequired)
        {
            grid.Invoke(新UpdateGridDelegate(UpdateGridSafe),新的对象[] {格,rowIdx,类型});
        }
        其他
        {
            如果(类型== 1)
                grid.Rows [rowIdx] .Cells [$ P $页] Style.ForeColor = Color.Red。
            如果(类型== 2)
                grid.Rows [rowIdx] .Cells [$ P $页] Style.ForeColor = Color.ForestGreen。

        }
    }
 

但是,当我进入UpdateGridSafe,该程序挂起。

在调试器,我看到grid.Invoke不调用UpdateGridSafe。请帮助 - 什么是错的。

修改

经典线程创建code

 线程t =新主题(新ParameterizedThreadStart(ThreadProc的));
        t.Start(dgvSource);
        t.Join();
        的MessageBox.show(完成,信息);
 

解决方案

您有一个僵局。您t.Join挡住了GUI线程,直到ThreadProc的完成。 ThreadProc的被阻塞,等待t.Join完成,因此它可以做到的调用。

为code

 线程t =新主题(新ParameterizedThreadStart(ThreadProc的));
    t.Start(dgvSource);
    t.Join(); < ---僵局程序
    的MessageBox.show(完成,信息);
 

好code

  backgroundWorker1.RunWorkerAsync

  私人无效backgroundWorker1_DoWork(对象发件人,
        DoWorkEventArgs五)
    {
        VAR电网=(DataGridView的)目标文件;
        的foreach(的DataGridViewRow行grid.Rows)
        {
            如果(Parser.Get preparationByClientNameForSynonims(row.Cells [$ P $页。Value.ToString())!= NULL)
                UpdateGridSafe(网格,row.Index,1);
            //不需要这个了Thread.Sleep(10);
        }
    }

   私人无效backgroundWorker1_RunWorkerCompleted(
            对象发件人,RunWorkerCompletedEventArgs E)
        {
        的MessageBox.show(完成,信息);
}
 

修改

还可以使用的BeginInvoke,而不是调用。这样,你的工作线程没有阻止每次更新GUI的时间。

参考

避免调用(),preFER的BeginInvoke()

I've got thread, which processes some analytic work.

   private static void ThreadProc(object obj)
    {
        var grid = (DataGridView)obj;
        foreach (DataGridViewRow row in grid.Rows)
        {
            if (Parser.GetPreparationByClientNameForSynonims(row.Cells["Prep"].Value.ToString()) != null)
                UpdateGridSafe(grid,row.Index,1);
            Thread.Sleep(10);
        }
    }

I want safely update my gridView at loop, so I use classic way:

    private delegate void UpdateGridDelegate(DataGridView grid, int rowIdx, int type);
    public static void UpdateGridSafe(DataGridView grid, int rowIdx, int type)
    {
        if (grid.InvokeRequired)
        {
            grid.Invoke(new UpdateGridDelegate(UpdateGridSafe), new object[] { grid, rowIdx, type });
        }
        else
        {
            if (type == 1)
                grid.Rows[rowIdx].Cells["Prep"].Style.ForeColor = Color.Red;
            if (type==2)
                grid.Rows[rowIdx].Cells["Prep"].Style.ForeColor = Color.ForestGreen;

        }
    }

But when I enter UpdateGridSafe, the program hangs.

In the debugger, I see that grid.Invoke doesn't invoke UpdateGridSafe. Please help - what's wrong?

EDIT

Classic thread create code

        Thread t = new Thread(new ParameterizedThreadStart(ThreadProc));
        t.Start(dgvSource);
        t.Join();
        MessageBox.Show("Done", "Info");

解决方案

You have a deadlock. Your t.Join is blocking the GUI thread until ThreadProc is done. ThreadProc is blocked waiting for t.Join to finish so it can do the Invokes.

Bad Code

    Thread t = new Thread(new ParameterizedThreadStart(ThreadProc)); 
    t.Start(dgvSource); 
    t.Join();  <--- DEADLOCK YOUR PROGRAM
    MessageBox.Show("Done", "Info"); 

Good Code

   backgroundWorker1.RunWorkerAsync

  private void backgroundWorker1_DoWork(object sender, 
        DoWorkEventArgs e)
    {    
        var grid = (DataGridView)obj;    
        foreach (DataGridViewRow row in grid.Rows)    
        {    
            if (Parser.GetPreparationByClientNameForSynonims(row.Cells["Prep"].Value.ToString()) != null)    
                UpdateGridSafe(grid,row.Index,1);    
            // don't need this Thread.Sleep(10);    
        }    
    }  

   private void backgroundWorker1_RunWorkerCompleted(
            object sender, RunWorkerCompletedEventArgs e)
        {
        MessageBox.Show("Done", "Info"); 
}

EDIT

Also use BeginInvoke instead of Invoke. That way your worker thread doesn't have to block every time you update the GUI.

Reference

Avoid Invoke(), prefer BeginInvoke()

这篇关于通过调用从后台线程C#线程问题的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆