【问题标题】:C# Debug build ok, but Release build fail due to optimizedC# Debug build ok,但 Release build 由于优化而失败
【发布时间】:2018-06-13 10:18:19
【问题描述】:

似乎是由于编译器优化:(.net 4.0,VS2015), 这是触摸屏的后台工作者。

DispatchService.BeginInvoke(() =>
{
    _vm = new TouchViewModel(Container.GetExportedValue<ITouchView>());
    _vm.ShowDialog();
});

// the background worker waiting for the Dialog show up
while (_vm == null) ; // Trace.WriteLine($"Wait _vm");
// Get Packet from Touch Panel
_vm.Points.Add(packet);
// (draw on the dialog via data binding)

它在“调试”构建时工作,但在“发布”构建时永远循环。 如果在 while 循环中添加 Trace.WriteLine,它也可以工作。 解决这个问题的正确方法是什么?

没有等待/异步,因为 WinXP 兼容(.NET 4.0)

【问题讨论】:

  • 你想做什么? while (_vm == null) ; 是灾难的秘诀
  • 该代码看起来有点讨厌,您正在调度调用以实例化一个对象并在一个紧密的循环中等待它返回。可能是调试代码的时间允许它工作。
  • 为什么不使用while (true) { }
  • while (_vm == null) 循环中的 _vm 可能正在注册。有一系列技巧可以避免这个问题 - 从volatilelockThread.VolatileRead 等 - 但坦率地说,这首先是一件丑陋的事情......
  • 试试while (Volatile.Read(ref _vm) == null) ;,但这整个忙循环真的不好。最好使用ManualResetEvent,在分配_vm 时设置它,然后等待事件而不是while 循环。

标签: c# wpf debugging release


【解决方案1】:

如果您需要阻止执行,直到委托将在其他线程中执行,那么实现适当的同步是关键。

例如,您可以使用Monitor

// field somewhere
readonly object _lock = new object();

// then
DispatchService.BeginInvoke(() =>
{
    _vm = new TouchViewModel(Container.GetExportedValue<ITouchView>());
    lock(_lock)
        Monitor.Pulse(_lock);
    _vm.ShowDialog();
});
lock(_lock)
    Monitor.Wait(_lock);    

【讨论】:

  • 我以为您想等待对话框关闭,但在您编辑问题时,您似乎只想在显示对话框时执行一些代码(您是在等待对话框出现还是只是为了 @ 987654324@初始化?)。如果是这样,那么可能更好的解决方案是订阅事件,例如Loaded 并在那里运行代码。
  • 嗨,Sinatr,你明白了我的目的。我使用 MVVM,那些源代码在 Application 程序集中,而不是 Presentation 程序集中,所以应该没问题。感谢您的评论!
  • 最后我使用 ManualResetEventSlim
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-12-16
  • 1970-01-01
  • 1970-01-01
  • 2019-09-28
  • 2018-10-15
相关资源
最近更新 更多