有form类Dbview,form类form1,线程类C。Dbview是主类,form1从Dbview启动(点击监控按钮),Dbview界面点击连接按钮后根据输入数据多少启动1到n个线程(线程方法实现根据线程类C)称这些线程为C1至Cn线程,C1到Cn使用线程类C的方法从opc循环获取数据,再通过2个委托传值给Dbview和form1。form1中用datagridview显示数据,使用方法getopcdata(getopcdata方法写在form1中)和线程类C中委托绑定,有数据就传送到getopcdata,再在方法体中修改datagridview的值。
现在一个问题是,我是用非创建datagirdview的线程修改datagirdview中表格的值(不使用invoke直接修改UI),并没有每次都弹出异常,而是极少次数报异常,这是为什么。
程序的使用是先点击连接按钮启动线程获取opc数据,然后点击监控按钮启动form1让获取的数据显示在form1上。
第二个问题是在使用invoke时,先点击连接按钮再点击监控可以正常显示,但是一旦关了form1,c1到cn线程就不再运行了,必须点连接重新启动c1-cn线程,但是不使用invoke直接修改UI时c1到cn就可以一直正常运行,这是为什么,如何在关闭form1之后继续使c1-cn正常运行
下面是在getopcdata中修改ui的代码(不使用invoke直接修改UI)
public void getopcdata(Dictionary<string, Store> dictbuffer)
{
try
{
if (dictoutput.Count > 0)
{
dataGridView1.RowCount = dictoutput.Count;
for (int i = 0; i < dictoutput.Count; i++)
{
foreach (var item in dictbuffer)
{
if (item.Key.ToString().Equals(dataGridView1.Rows[i].Cells[0].Value.ToString()))
{
dataGridView1.Rows[i].Cells[1].Value = item.Value.value;
}
}
}
}
}
catch (Exception ex)
{
MessageBox.Show(ex.ToString());
}
当我使用跨线程Invoke的时候getopcdata方法如下
public void getopcdata(Dictionary<string, Store> dictbuffer)
{
if (dataGridView1.InvokeRequired)
{
dataGridView1.Invoke(new MethodInvoker(delegate ()
{
if (dictoutput.Count > 0)
{
dataGridView1.RowCount = dictoutput.Count;
for (int i = 0; i < dictoutput.Count; i++)
{
foreach (var item in dictbuffer)
{
if (item.Key.ToString().Equals(dataGridView1.Rows[i].Cells[0].Value.ToString()))
{
dataGridView1.Rows[i].Cells[1].Value = item.Value.value;
}
}
}
}
}));
}
}
线程类C代码
public class OpcRead
{
public delegate void MyCallback(Dictionary<string, Store> dictbuffer);
private MyCallback myCallback;
private MyCallback form1Callback;
public Dictionary<string, string> dict = new Dictionary<string, string>();
public OPCUAHelper opc;
public string root_url;
public OpcRead(Dictionary<string, string> dict1, OPCUAHelper opc, string root_url, MyCallback callback,MyCallback callbackform1)
{
this.myCallback = callback;
this.form1Callback = callbackform1;
this.dict = dict1;
this.opc = opc;
this.root_url = root_url;
}
public void readopc()
{
Dictionary<string, Store> dictbuffer=new Dictionary<string, Store>();
while (GlassProcess.DbView.running)
{
if (dict.Count>0)
{
for (int i = 0; i < dict.Count; i++)
{
var name = dict.Keys.ElementAt(i);
var connection = dict.Values.ElementAt(i);
string threadname = Thread.CurrentThread.Name;
if (!connection.Equals("null"))
{
var value = opc.GetCurrentNodeValue<ValueType>(connection);
if (value == null)
{
MessageBox.Show(name + "读取错误");
Store store = new Store(name,connection,threadname);
GlassProcess.DbView.dictretry.Add(name,store);
dict.Remove(name);
break;
}
else
{
Store store = new Store(name,root_url,threadname,value);
if (!dictbuffer.ContainsKey(name))
{
dictbuffer.Add(name, store);
}
else if (dictbuffer.ContainsKey(name))
{
dictbuffer.Remove(name);
dictbuffer.Add(name, store);
}
}
}
}
myCallback(dictbuffer); //通过委托将dictbuffer发送给Dbview
form1Callback(dictbuffer); //通过委托将dictbuffer发送给form1
dictbuffer.Clear();
}
Thread.Sleep(100);
}
}
}
}