Datagridview C#的多线程 [英] Multithreading with Datagridview C#

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

问题描述

这里我正在做一个检查用户名的过程。我从文本文件创建了一个datagridview和加载的数据。所以datagridview包含头两个列中的用户的名字和姓氏。我需要做的是逐行读取这些值,并发现第一个和最后一个没有相同的名称。这些操作是在单独的类中执行的。所以我需要从该类获得结果,并将结果显示给gridview。当我使用一个线程时,这一切都很好。但是当我使用多个线程时,只会在gridview读取中抛出一个异常outofbound异常。这是我的编码:

  static int i,j = 0,l = 0,k = 0,m = 0; 

public void check()
{
for(i = 0; i< dataGridView1.Rows.Count; i ++)
{
if InvokeRequired)
{
Invoke(new UpdateDelegate(delegate
{
if(i == 0&& j == 0)
{
DataGridViewColumn col = new DataGridViewTextBoxColumn();
col.HeaderText =Status;
int colIndex = dataGridView1.Columns.Add(col);
dataGridView1.Rows [i] .Cells [colIndex ] .Value =Process Started;
j = 1;
}
else
{
dataGridView1.Rows [i] .Cells [3] .Value =进程开始;
}
}));
}

if(InvokeRequired)
{
Invoke(new UpdateDelegate(delegate
{
Process obj_reg = new Process(dataGridView1.Rows [i] .Cells [1] .Value.ToString(),dataGridView1.Rows [i] .Cells [2] .Value.ToString());
string res = obj_reg.register();
Thread.Sleep(500);
if(res.Contains(success))
{
if(i == 0&& k == 0)
{
DataGridViewColumn col = new DataGridViewTextBoxColumn();
col.HeaderText =Result;
int colIndex = dataGridView1.Columns.Add(col);
dataGridView1.Rows [我] .Cells [colIndex] .Value =Ya its different;
dataGridView1.Rows [i] .DefaultCellStyle.BackColor = Color.Green;
k = 1;
}
else
{
dataGridView1.Rows [i] .Cells [4] .Value =Ya it different;
dataGridView1.Rows [i] .DefaultCellStyle.BackColor = Color.Green;
}
}
else
{
if(i == 0&& m == 0)
{
DataGridViewColumn col = new DataGridViewTextBoxColumn();
col.HeaderText =Result;
int colIndex = dataGridView1.Columns.Add(col);
dataGridView1.Rows [i] .Cells [colIndex] .Value =不一样;
dataGridView1.Rows [i] .DefaultCellStyle.BackColor = Color.Red;
m = 1;
}
else
{
dataGridView1.Rows [i] .Cells [4] .Value =不一样;
dataGridView1.Rows [i] .DefaultCellStyle.BackColor = Color.Red;

}
}
}));
}
}
}

public void Button1_Click(Object sender,EventArgs e)
{
Thread [] threads = new Thread [ 3]; (int l = 0; l <3; l ++)
{
threads [l] = new Thread(new ThreadStart(check));

}
foreach(线程中的线程)
{
t.Start();
}
}

请建议我如何在这里使用多线程它只是一个例子..请解释任何其他方式..

解决方案

这段代码有几个问题。


  1. 您正在从工作线程访问 DataGridView 。在检查中的第一行代码显而易见。你不能这样做。


  2. 你定义了变量 i j l ,大概 k m (虽然我没有看到他们在任何地方声明)为静态。结果是,每个工作线程将使用相同的值并且相互对齐的脚趾。对于 i 来说,这是一个更大的问题,因为它实际上是从工作线程访问的。其他人从匿名代理访问,该代理被封送到UI线程上。但是,这可能会导致很多混乱,因为匿名代理执行的顺序是不可预测的。


  3. 您正在调用从工作线程调用。这本身不是问题。但是,考虑到您将所有有用的工作整理到UI线程上是没有意义的。想想吧你去所有的工作,使用工作线程,然后你把所有的东西回到UI线程无论如何。你现在有一个比你没有使用任何工作线程更糟的解决方案。


  4. 这不是一个问题,但更多的是我有。为什么打扰调用 InvokeRequired ?你已经知道调用是必需的,因为你在开发时知道这些东西在工作线程上。


我的建议如下。


  1. 根本不要使用线程。在这种情况下是毫无意义的。可以在另一个线程上执行的唯一有用的工作是比较名字和姓氏。这是微不足道的,可以在UI线程上快速完成。


  2. 如果你真的想使用一个单独的线程,那么你从UI线程上的 DataGridView 中读取值,并将它们放在单独的数据结构中;一个可以从另一个线程使用的。当您开始长时间运行的时候,您将不需要阅读网格,因此您可以通过 DataGridView 来保持此数据结构。将数据复制到这个单独的数据结构中。



Here i'm doing one process of checking user names. I've created one datagridview and loadded data from the text file. so the datagridview contains first name and last name of users in first two columns . What i need to do is read those values row by row and find that there is no same name for first and last .These operation is performed in separate class. So i need to get result from that class and show the result to gridview alternatively . It all works fine when i'm using just one thread . But when i'm using more than one thread it just throwing an exception that outofbound exception in gridview reading . Here is my coding :

static int i, j=0, l=0,k=0,m=0;

public void check()
{ 
    for (i = 0; i < dataGridView1.Rows.Count ; i++)
    {
        if (InvokeRequired)
        {
            Invoke(new UpdateDelegate(delegate
                {
                    if (i == 0 && j==0)
                    {
                        DataGridViewColumn col = new DataGridViewTextBoxColumn();
                        col.HeaderText = "Status";
                        int colIndex = dataGridView1.Columns.Add(col);
                        dataGridView1.Rows[i].Cells[colIndex].Value = "Process Started";
                        j = 1;
                    }
                    else
                    {
                        dataGridView1.Rows[i].Cells[3].Value = "process Started";            
                    }
                }));
        }

        if (InvokeRequired)
        {
            Invoke(new UpdateDelegate(delegate 
                { 
                    Process obj_reg = new Process(dataGridView1.Rows[i].Cells[1].Value.ToString(),dataGridView1.Rows[i].Cells[2].Value.ToString());
                    string res = obj_reg.register();
                    Thread.Sleep(500);
                    if (res.Contains("success"))
                    {
                        if (i == 0 && k==0)
                        {
                            DataGridViewColumn col = new DataGridViewTextBoxColumn();
                            col.HeaderText = "Result";
                            int colIndex = dataGridView1.Columns.Add(col);
                            dataGridView1.Rows[i].Cells[colIndex].Value = "Ya its different";
                            dataGridView1.Rows[i].DefaultCellStyle.BackColor = Color.Green;
                            k = 1;
                        }
                        else 
                        {
                            dataGridView1.Rows[i].Cells[4].Value = "Ya its different";                              
                            dataGridView1.Rows[i].DefaultCellStyle.BackColor = Color.Green;
                        }
                    }
                    else
                    {
                        if (i == 0 && m == 0)
                        {
                            DataGridViewColumn col = new DataGridViewTextBoxColumn();
                            col.HeaderText = "Result";
                            int colIndex = dataGridView1.Columns.Add(col);
                            dataGridView1.Rows[i].Cells[colIndex].Value = "No its same";
                            dataGridView1.Rows[i].DefaultCellStyle.BackColor = Color.Red;
                            m = 1;
                        }
                        else
                        {
                            dataGridView1.Rows[i].Cells[4].Value = "No its same";
                            dataGridView1.Rows[i].DefaultCellStyle.BackColor = Color.Red;

                        }
                    }
                }));
        }
    }
}

public void Button1_Click(Object sender, EventArgs e)
{
    Thread[] threads = new Thread[3];
    for (int l = 0; l < 3; l++)
    {
        threads[l] = new Thread(new ThreadStart(check));
    }
    foreach (Thread t in threads)
    {
        t.Start();
    }
}

Please suggest me how to use Multithread here ... its just an example .. please explain any other way ..

解决方案

There are several problems with this code.

  1. You are accessing the DataGridView from a worker thread. This is evident by the first line of code in check. You simply cannot do this.

  2. You defined the variables i, j, l, and presumably k and m (though I do not see them declared anywhere) as static. The consequence is that each worker thread will be working with the same values and stepping on each other's toes. It is a bigger problem for i since it actually is being accessed from the worker thread. The others are accessed from anonymous delegate which is marshaled onto the UI thread. Still, that is probably going to cause a lot of confusion because the order in which anonymous delegates are getting executed is unpredictable.

  3. You are calling Invoke from the worker thread. This is not a problem by itself. But, considering that you are mashaling all of the useful work back onto the UI thread it is rather pointless. Think about it. You went to all that work to use a worker thread and then you marshal everything back onto the UI thread anyway. You now have a solution that is worse than had you not used any worker threads at all.

  4. This is not a problem really, but more of a gripe I have. Why bother calling InvokeRequired? You already know that "invoking" is required because you know at development time that this stuff is on a worker thread.

My recommendations are as follows.

  1. Do not use threads at all. It is pointless in this case. The only useful work that can be performed on a another thread is the comparison of the first and last names. That is trivial and can be done just as quickly on the UI thread.

  2. If you really want to use a separate thread then you have to read the values from the DataGridView on the UI thread and put them in a separate data structure; one that is safe to use from another thread. It would be better to maintain this data structure in tandem with the DataGridView that way when it comes time to initiate your long running operation you will not need to read the grid since you already have the data copied into this separate data structure.

这篇关于Datagridview C#的多线程的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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