我目前遇到一个问题,这似乎与关闭表单有关,而通过串行连接连接的秤不断发送数据(每 sek 大约 3 个包)。
我通过 DataReceived-Event 处理新数据(处理本身可能对这个问题没有兴趣,因为我只是匹配数据)密切关注 COM_InUse 变量和 allowFireDataReceived 检查。):
private void COMScale_DataReceived(object sender, EventArgs e)
{
if (allowFireDataReceived)
{
//set atomar state
COM_InUse = true;
//new scale:
if (Properties.Settings.Default.ScaleId == 1)
{
strLine = COMScale.ReadTo(((char)0x2).ToString());
//new scale:
Regex reg = new Regex(Constants.regexScale2);
Match m = reg.Match(strLine);
if (m.Success)
{
strGewicht = m.Groups[1].Value + m.Groups[2];
double dblComWeight;
double.TryParse(strGewicht, out dblComWeight);
dblScaleActiveWeight = dblComWeight / 10000;
//add comma separator and remove zeros
strGewicht = strGewicht.Substring(0, 1) + strGewicht.Substring(1, 2).TrimStart('0') + strGewicht.Substring(3);
strGewicht = strGewicht.Insert(strGewicht.Length - 4, ",");
//write to textbox
ThreadSafeSetActiveScaleText(strGewicht);
COMScale.DiscardInBuffer();
//MessageBox.Show(dblScaleActiveWeight.ToString(), "dblScaleActiveWeight");
}
}
//free atomar state
COM_InUse = false;
}
}
COM_InUse 变量是一个全局布尔值,“告诉”当前是否存在处理数据的进程。allowFireDataReceived 也是一个全局布尔值,如果设置为 false,则不会对已发送的数据进行额外处理。
我现在的问题如下:
似乎 Eventhandling 是一个单独的线程,这会导致单击取消按钮时出现死锁,因为即使处理了事件,COM_InUse 也永远不会变为 false(请参阅 COMScale_DataReceived 的结尾,其中 COM_InUse 设置为 false)。虽然设置 allowFireDataReceived = false 完美工作(不再处理),正如我所说:while循环不会终止。
private void bScaleCancel_Click(object sender, EventArgs e)
{
allowFireDataReceived = false;
while (COM_InUse)
{
;
}
if (!COM_InUse)
{
ret = 1;
SaveClose();
}
}
当我注释掉 while 块时,我必须在按钮上单击两次,但它可以正常工作而不会崩溃。由于这种用户非常不友好,我正在寻找一种安全关闭窗口的替代方法。
信息:简单地关闭(不检查是否处理了 COM 数据)会导致致命的崩溃。
所以,也许有人可以向我解释究竟是什么导致了这个问题,或者可以提供解决方案。(也许会再次触发 Cancel-Clicking 事件,但这很丑陋)
问候!
我全靠你了 :)
//编辑:这是当前的代码
private void ThreadSafeSetActiveScaleText(string text)
{
// InvokeRequired required compares the thread ID of the
// calling thread to the thread ID of the creating thread.
// If these threads are different, it returns true.
if (this.lScaleActive.InvokeRequired)
{
SafeActiveScaleTextCallback d = new SafeActiveScaleTextCallback(ThreadSafeSetActiveScaleText);
this.Invoke(d, new object[] { text });
}
else
{
this.lScaleActive.Text = text;
}
}