我是并行编程的新手,在尝试绘制测量结果时,我遇到了臭名昭着的错误“控制控件名称从一个线程访问,而不是它创建的线程。”
经过数小时的网页浏览和失败的实验后,我不得不放弃并寻求建议。
我想要做的是在程序继续执行时在单独的线程中进行一些绘图。
在绘图程序中(在Panel控件上)我非常广泛地使用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...
}
Ciao,感谢您的关注。
佛朗哥
答案 0 :(得分:0)
解决!!
越来越多的网页浏览时间给了他们成果!
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(...)继续返回零...
Ciao和下一个。
佛朗哥