我有一个C ++库,可以实现与硬件的一些通信。由于倾向于与用户交互的主要应用程序是用.Net(使用Windows窗体)编写的,因此我在C ++库周围编写了一个小型包装,并将方法编组为.NET。 C ++包装器是一个简单的单例类,它创建一个实例并允许调用函数:
WRAPPER_API Dev& Wrapper::getInstance()
{
static Dev instance;
return instance;
}
WRAPPER_API int iConnect() {
return Wrapper::getInstance().iConnect();
}
WRAPPER_API int iGetStatus() {
return Wrapper::getInstance().iGetStatus();
}
因此,创建了WFM,并且连接和第一个状态检索成功(iConnect返回0,iGetStatus返回0)。当我创建一个新线程并将实例传递给它时,问题就开始了(我需要并行线程每2秒检索一次状态信息)。但是,并行线程中iGetStatus的所有调用均返回-1(表示未建立与设备的连接)。
这是我使用的代码:
namespace DeviceTest
{
public partial class Form1 : Form
{
Dev _api = null;
System.Threading.ManualResetEvent _mr = new System.Threading.ManualResetEvent(false);
bool _exit = false;
Thread _pool = null;
SynchronizationContext _context;
public Form1(Dev api)
{
InitializeComponent();
System.Drawing.Rectangle workingRectangle = Screen.PrimaryScreen.WorkingArea;
// Set the size of the form slightly less than size of
// working rectangle.
this.Size = new System.Drawing.Size(800, workingRectangle.Height - 200);
this.ClientSize = new System.Drawing.Size(this.Size.Width, this.Size.Height);
this.LogTB.Size = new System.Drawing.Size(this.LogTB.Size.Width, this.Size.Height - this.LogTB.Location.Y - 30);
this._api = api;
this.buttonEXIT.Click += (s, e) => this.Close();
_mr.Reset();
this._pool = new Thread((o) =>
{
_mr.WaitOne();
int i = 0;
Dev ap = (Dev)o;
Thread.Sleep(2000);
while (!this._exit && (i < 10))
{
var t = ap.iGetStatus();
Thread.Sleep(2000);
i++;
}
});
this.HandleCreated += (a, b) =>
{
this.buttonStartStatusThread.Click += (s, e) =>
{
this._api.iConnect();
this._api.iGetStatus();
_mr.Set();
};
}
}
有趣的是,如果我在线程中的iGetStatus之前调用iConnect-一切运行良好。
可能会因为同步而错过某些东西吗?
P.S.我已经在C ++和.Net控制台应用程序中使用相同的包装器测试了多线程-一切正常。只有WinForms会出现此问题。
答案 0 :(得分:0)
看起来这里的主要问题是“线程返回-1(表示未建立与设备的连接)”。您是否将c ++硬件状态检查器作为独立应用程序进行了测试(.Net系统外部)?也许是操作系统特权的问题,应用程序在用户模式下运行,驱动程序(访问硬件)应在内核模式下执行。