我是并行编程的新手,在尝试绘制测量结果时,我遇到了臭名昭著的错误“控制控件名称从创建它的线程以外的线程访问。” .
经过几个小时的网页浏览和失败的实验,我不得不放弃并寻求建议。
我想做的是在程序继续执行的同时在单独的线程中进行一些绘图。
在绘图例程中(在面板控件上)我使用了相当广泛的 API 调用(Polyline、BitBlt 等...),其中我必须使用 IntPtr hDCh_Dst = Win32.GetDC(pnlSchermo.Handle)。
我在网上找到了数以千计的针对此问题的建议解决方案(几乎全部用于设置属性,少数用于获取),但我无法使它们正常工作。
这是我目前正在 WFA 项目中测试的(简化的)代码。
do
{
// Data acquisition and processing...
// etc...
// Plot the measurement results...
Thread thrDisegna = new Thread(() => DisegnaGrafico(NcF: NcZxF));
thrDisegna.Start();
// Do some other processing...
// Wait for the end of the plot job:
while (thrDisegna.IsAlive);
}
while (bMisuraOn);
private void DisegnaGrafico(string HcTipo = "", int NcF = 0)
{
// Some initialisations...
// Call the method XY in the Class QL (that is an instance of the Class Quadro) for scaling the pnlSchermo control and do some API plot:
QL.XY(pnlSchermo, ..., ..., ref hdcDst, ..., ...);
// Some other API plotting using the hdcDst...
}
public void XY(Panel pnlSchermo, ..., ..., ref IntPtr hdcDst, ..., ...))
{
// ...
// Here is where I need to use the pnlSchermo.Handle:
hDCh_Dst = Win32.GetDC(pnlSchermo.Handle); // <-- Fails with the "Control control name accessed ..." exception.
// or... but doesn't work either and the program hangs:
pnlSchermo.Invoke(new MethodInvoker(delegate() { hDCh_Dst = Win32.GetDC(pnlSchermo.Handle); }));
// or... the program doesn't hangs, no exception thrown but returns _hDCh_Dst = 0. Does it need a EndInvoke?
IntPtr _hDCh_Dst = IntPtr.Zero;
pnlSchermo.BeginInvoke(new MethodInvoker(delegate
{
_hDCh_Dst = pnlSchermo.Handle;
}));
hDCh_Dst = Win32.GetDC(_hDCh_Dst);
// or... other solutions found on the Web and tested without success...
}
再见,感谢关注。
佛朗哥
解决了!!
越来越多的网页浏览时间带来了成果!
Control.Invoke 挂起应用程序的问题是由于 Invoke 的交叉干扰,它在返回之前等待其完成,并且主线程在以下位置循环:
同时(thrDisegna.IsAlive);
将这一行替换为:
做 { Application.DoEvents(); } while (thrDisegna.IsAlive);
让以下句柄访问方法起作用:
IntPtr hDCh_Dst1 = IntPtr.Zero;
pnlSchermo.Invoke(new MethodInvoker(delegate() { hDCh_Dst1 = Win32.GetDC(pnlSchermo.Handle); }));
hDCh_Dst = hDCh_Dst1;
现在,出于好奇,我必须调查为什么 pnlSchermo.BeginInvoke(...) 继续返回零...
再见,下一个。
佛朗哥
我是一名优秀的程序员,十分优秀!