C# WPF 机器相关的并发问题
C# WPF Machine-Dependent Concurrency Issues
我有一个多线程 C# WPF 应用程序,它是一个更大软件(Princeton Instruments LightField,对于那些感兴趣的人)的插件。
我的插件在独立于 GUI 的线程上调用同步方法。此方法来自相机 API 并从相机捕获 n 秒曝光和 returns 捕获的帧。
情况看起来是这样的:
private static volatile bool _STOP = true;
// Runs when the "Run" button is clicked
private void Run_Click(object sender, RoutedEventArgs e)
{
object time = InputTime.Text; // a non-negative integer provided by the user
_STOP = false;
Thread run_thread = new Thread(Running);
run_thread.Start(time);
}
// Runs when the "Stop" button is clicked
private void Stop_Click(object sender, RoutedEventArgs e)
{
_STOP = true;
}
// Separate Thread from GUI
private void Running(object t)
{
int time = Convert.ToInt32(t);
FrameObject f;
while(!_STOP)
{
// synchronously capture a t-second exposure
f = CameraAPI.CaptureImage(t);
// display the exposure on a viewer controlled by the parent thread
Application.Current.Dispatcher.BeginInvoke(new Action(Viewer.Display(f));
}
}
这段代码(或者更确切地说,它是更复杂的同级代码)在我开发它的计算机(计算机 A)上运行得非常好。我单击 运行,整个应用程序在代码为 运行ning 时保持响应。
当我尝试在将定期托管它的计算机(计算机 B)上 运行 它时,出现以下行为:
- 单击 运行 按钮时,GUI 停止响应 n
秒(n 是发送到
CameraAPI.CaptureImage(n);
方法)。对于任何正整数 n 都会发生这种情况,并且随着
while 循环在每个循环周期执行此方法(即应用程序冻结 n 秒,在调用 Display 方法时有一个短暂的解冻时刻,然后应用程序再次冻结 n 秒)。
- 如果我调用
Thread.Sleep(n);
代替
CameraAPI.CaptureImage(n);
,应用程序没有冻结。
- 不仅仅是我的插件冻结了——整个应用程序都冻结了。
- 我已将我的代码从计算机 A 构建、重建、删除并重新复制到计算机 B,但错误仍然存在。
- 计算机 A(我构建它的地方)是相同的(据我所知)
到有问题的计算机(计算机 B)。处理器,OS,
驱动器、RAM、应用程序版本等都是相同的。电脑A
专门存在,以便可以开发应用程序
计算机 B.
- 删除
Application.Current.Dispatcher.BeginInvoke(new Action(Viewer.Display(f));
行不会停止 GUI 冻结。这不是问题方法。
- 该应用程序在每台计算机上使用相同数量的线程 (43)。当插件是 运行ning 时,线程数在每台计算机上增加相同的数量(1-4 取决于我们在程序中的位置)。
所以,在两个看似相同的系统上,相同的代码却有不同的结果。在系统 A 上,它按预期工作(没有 GUI 冻结),而在系统 B 上,整个应用程序的 GUI——不仅仅是我正在编写的插件——在每次调用同步方法时都会冻结。
这个错误行为超出了我对计算机的理解,所以现在我来了。关于导致这种行为差异的原因有什么想法吗?
我们重新安装了父应用程序,一切正常。仍然不知道为什么会发生这种情况,但由于问题已解决,因此关闭了问题。 "turn it off and back on again."
的真实案例
我有一个多线程 C# WPF 应用程序,它是一个更大软件(Princeton Instruments LightField,对于那些感兴趣的人)的插件。
我的插件在独立于 GUI 的线程上调用同步方法。此方法来自相机 API 并从相机捕获 n 秒曝光和 returns 捕获的帧。
情况看起来是这样的:
private static volatile bool _STOP = true;
// Runs when the "Run" button is clicked
private void Run_Click(object sender, RoutedEventArgs e)
{
object time = InputTime.Text; // a non-negative integer provided by the user
_STOP = false;
Thread run_thread = new Thread(Running);
run_thread.Start(time);
}
// Runs when the "Stop" button is clicked
private void Stop_Click(object sender, RoutedEventArgs e)
{
_STOP = true;
}
// Separate Thread from GUI
private void Running(object t)
{
int time = Convert.ToInt32(t);
FrameObject f;
while(!_STOP)
{
// synchronously capture a t-second exposure
f = CameraAPI.CaptureImage(t);
// display the exposure on a viewer controlled by the parent thread
Application.Current.Dispatcher.BeginInvoke(new Action(Viewer.Display(f));
}
}
这段代码(或者更确切地说,它是更复杂的同级代码)在我开发它的计算机(计算机 A)上运行得非常好。我单击 运行,整个应用程序在代码为 运行ning 时保持响应。
当我尝试在将定期托管它的计算机(计算机 B)上 运行 它时,出现以下行为:
- 单击 运行 按钮时,GUI 停止响应 n
秒(n 是发送到
CameraAPI.CaptureImage(n);
方法)。对于任何正整数 n 都会发生这种情况,并且随着 while 循环在每个循环周期执行此方法(即应用程序冻结 n 秒,在调用 Display 方法时有一个短暂的解冻时刻,然后应用程序再次冻结 n 秒)。 - 如果我调用
Thread.Sleep(n);
代替CameraAPI.CaptureImage(n);
,应用程序没有冻结。 - 不仅仅是我的插件冻结了——整个应用程序都冻结了。
- 我已将我的代码从计算机 A 构建、重建、删除并重新复制到计算机 B,但错误仍然存在。
- 计算机 A(我构建它的地方)是相同的(据我所知) 到有问题的计算机(计算机 B)。处理器,OS, 驱动器、RAM、应用程序版本等都是相同的。电脑A 专门存在,以便可以开发应用程序 计算机 B.
- 删除
Application.Current.Dispatcher.BeginInvoke(new Action(Viewer.Display(f));
行不会停止 GUI 冻结。这不是问题方法。 - 该应用程序在每台计算机上使用相同数量的线程 (43)。当插件是 运行ning 时,线程数在每台计算机上增加相同的数量(1-4 取决于我们在程序中的位置)。
所以,在两个看似相同的系统上,相同的代码却有不同的结果。在系统 A 上,它按预期工作(没有 GUI 冻结),而在系统 B 上,整个应用程序的 GUI——不仅仅是我正在编写的插件——在每次调用同步方法时都会冻结。
这个错误行为超出了我对计算机的理解,所以现在我来了。关于导致这种行为差异的原因有什么想法吗?
我们重新安装了父应用程序,一切正常。仍然不知道为什么会发生这种情况,但由于问题已解决,因此关闭了问题。 "turn it off and back on again."
的真实案例