C# 从另一个线程(在另一个类中)向数据网格添加数据

C# 从另一个线程(在另一个类中)向数据网格添加数据,c#,multithreading,C#,Multithreading,我有一个问题,好几天来一直让我发疯。。我已经尝试了很多来自这个网站和其他网站的教程和代码片段。我正在构建P2P应用程序,访问主线程时遇到问题。 下面是我的应用程序的简单流程: 1.显示frmMain-用户单击登录按钮 2.显示frmlogin-用户输入其姓名 3.“登录”后-创建两个线程(threadTCPlistener和threadUDPlistener) 4.显示frmDataGrid Server listen = new Server(); Thread listeningUDPThr


我有一个问题,好几天来一直让我发疯。。我已经尝试了很多来自这个网站和其他网站的教程和代码片段。我正在构建P2P应用程序,访问主线程时遇到问题。
下面是我的应用程序的简单流程:
1.显示frmMain-用户单击登录按钮
2.显示frmlogin-用户输入其姓名
3.“登录”后-创建两个线程(threadTCPlistener和threadUDPlistener)
4.显示frmDataGrid

Server listen = new Server();
Thread listeningUDPThread = new Thread(new ThreadStart(listen.startUDPServer));
listeningUDPThread.IsBackground = true;
listeningUDPThread.Start();
Thread listeningTCPThread = new Thread(new ThreadStart(listen.startTCPServer));
listeningTCPThread.IsBackground = true;
listeningTCPThread.Start();
frmDataGrid dg = new frmDataGrid();
dg.Show();
5.线程在一个称为“服务器”的单独类中工作。在那里,它们等待传入的连接,当TCP线程接受连接时,它开始接收文件。收到该文件后,我想更改frmDataGrid中的GUI,以便在grid视图中添加新行。我做过这样的事情:

public void downloadFile()
{
     //--receiving of the file--
     frmDataGrid fdg = new frmDataGrid();
     //filename is the name of received file, and 100's are just for testing (for now).    
     fdg.verifyUIRequest(fileName, 100, 100);
}
 public void verifyUIRequest(string filename, int done, int percent)
     {
     if (dgvDown.InvokeRequired)
         {
         dgvDown.Invoke((MethodInvoker)delegate { updateDownDgv(filename, done, percent);  });
         }
     else
     {
         updateDownDgv(filename, done, percent);
     }
我正在从frmDataGrid VerifyUIRequest调用一个如下所示的方法:

public void downloadFile()
{
     //--receiving of the file--
     frmDataGrid fdg = new frmDataGrid();
     //filename is the name of received file, and 100's are just for testing (for now).    
     fdg.verifyUIRequest(fileName, 100, 100);
}
 public void verifyUIRequest(string filename, int done, int percent)
     {
     if (dgvDown.InvokeRequired)
         {
         dgvDown.Invoke((MethodInvoker)delegate { updateDownDgv(filename, done, percent);  });
         }
     else
     {
         updateDownDgv(filename, done, percent);
     }
在此之后,主线程应该调用“updateDownDgv”方法,但问题是我的数据网格没有发生任何事情。以下是更新代码:

public void updateDownDgv(string filename, int done, int percent)
{
foreach (DataGridViewRow r in dgvDown.Rows)
{
        if ((string)r.Cells[0].Value == filename)
                {
                    r.Cells[1].Value = done;
                    r.Cells[2].Value = percent;
                }
                dgvDown.Invalidate();
                return;
 }
 DataTable tab = (DataTable)dgvDown.DataSource;
 DataRow row =  tab.NewRow();
 row[0] = filename;
 row[1] = percent;
 row[2] = done;
 //MessageBox.Show(done.ToString());
 tab.Rows.Add(row);
 dgvDown.DataSource = null;
 dgvDown.DataSource = tab;
 }
我曾经尝试过使用begin invoke,使用一些lambda表达式,但没有成功。有人能告诉我一个错误或者用其他方式帮助我吗?我会非常感激的。 PS这是我的第一篇文章,如果格式不好,我提前道歉。:)

编辑: 很明显,问题在于实例,所以我做了如下工作: 从我创建frmDataGrid类实例的服务器类,我现在调用它的构造函数,该构造函数包含3个参数。 frmDataGrid fdg=新的frmDataGrid(文件名,100100); 在该构造函数中,在frmDataGrid中,我调用verifyUIRequest。但接着又发生了另一个错误,我似乎无法理解。停在

if (dgvDown.InvokeRequired)
{...
错误如下所示:
“对象引用未设置为对象的实例”,即NullReferenceException。可能是什么错误?

您正在使用
下载文件
方法创建一个全新的数据网格。您应该更新主网格并从线程方法中调用该网格上的方法,而不是创建一个新网格,当
downloadFile
方法退出时,您可以将其放到地板上。

我认为如果您将问题分离开来,可能会有所帮助。尝试在根本不使用线程的情况下更新网格,看看它是否正常工作。之后,尝试使用线程,但没有gui,看看这是否有效。从一开始就将它们结合在一起很难解决。嗨,Amiram,线程工作得很好,即使是我放入
verifyUIRequest
方法中的线程,它们也能在完成时向我显示mbox。此外,数据网格可以直接更新(即使用主线程)。在
downloadFile
中,我只是创建类的一个实例,该类中包含旧的数据网格,而不是新的数据网格。在该实例中,我调用了一个方法来更新名为
dgvDown
(在
updateDgvDown
中)的旧数据网格。我不确定除了我正在使用的这个数据网格之外,我还应该用什么方式更新我的主数据网格。你确定吗?如果您为此表单两次调用“new”,那么您有两个数据网格。我不确定,可能是这样,但无论如何,我至少应该将该行添加到这个新网格中,并能够在我的表单中看到它。还是我应该?@epson121-你在表单中看到它的唯一方式是如果新的数据网格在表单上。如果新的datagrid没有添加到表单中,那么您将不会在表单中看到任何更新。关于你的第一个问题,
dgvDown
?您没有将其传递给
frmDataGrid
构造函数。