C# 在lambda中调用时未更新UI

C# 在lambda中调用时未更新UI,c#,wpf,C#,Wpf,我用的是一台电脑。 我想以动态/编程方式向UI添加按钮。 但是,对于以下代码段,没有添加任何按钮(但我看到控制台打印): discover方法的代码: public void discover(DeviceLocator.DeviceFoundEventHandler deviceFound) { DeviceLocator.OnDeviceFound += deviceFound; DeviceLocator.Discover(); } 用户界面XAML: <Windo

我用的是一台电脑。 我想以动态/编程方式向UI添加按钮。 但是,对于以下代码段,没有添加任何按钮(但我看到控制台打印):

discover
方法的代码:

public void discover(DeviceLocator.DeviceFoundEventHandler deviceFound) {
    DeviceLocator.OnDeviceFound += deviceFound;
    DeviceLocator.Discover();
}
用户界面XAML:

<Window x:Class="my_lights.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="AddControls" Height="114" Width="212">
    <StackPanel Name="splMain">
        <Button Click="btnAddMore_Click">Discover</Button>
    </StackPanel>
</Window>

发现

我怀疑这与lambda作用域有关,lambda作用域使用户无法访问UI。或者可能需要强制重新渲染。。但我还是迷路了。我试了很多东西。谢谢

问题是库在非UI线程中引发了
OnDeviceFound
。如果要在引发事件时操纵UI,则必须将其封送至UI线程:

private void btnAddMore\u单击(对象发送方,路由目标){
Button newBtn=新按钮{Content=“A new Button”};
splMain.Children.Add(newBtn);//按钮被添加
_yee.discover((o,args)=>{
开始(动作)(()=>{
Button newBtn2=new按钮{Content=args.Device.Hostname.ToString()};
splMain.Children.Add(newBtn2);//未添加任何按钮
}));
});
}

此外,您应该注意事件处理程序永远不会抛出异常;您可能不知道引发事件的代码将如何处理它。

尝试将与UI相关的代码包装到
Dispatcher中。Invoke
OnDeviceFound事件显然不会在UI线程上调用,这是访问任何UI元素所必需的。Dispatcher.Invoke或Dispatcher.BeginInvoke将调用封送到UI线程。克莱门斯是对的。从中可以看出,事件是在后台线程上引发的,该线程无权访问UI线程。代码还显示了库如何使用脏的空
catch
块吞没抛出的跨线程异常。非常糟糕的做法。这是为什么不这样做的一个很好的例子-尤其是在库代码中。异步代码也应该总是更喜欢异步
任务。延迟
而不是
线程。睡眠
。“这不是一个值得信赖的库。@andrew,因为我只是做了一个假设,没有深入研究提到的库(其他人已经这样做了,并向OP解释了一切)。此外,还有很多现有的问题,例如如何从WPFYou中的不同线程更新UI库的客户端代码应该自己处理异常或封送处理程序到UI线程。但在这种特殊情况下,客户机代码永远不会得到要处理的异常,因为它已经在库中被捕获
catch{}
将捕获每个异常,但不处理它,也不使用原始异常包装为内部异常的方式重新引发它。通常,上述代码的处理程序(无调度程序委派)将抛出跨线程异常。但是这个异常被吞没了,因为客户机继续执行,没有任何异常被抛出。这是库的实现细节引入的一个问题:空的
catch
语句阻止原始异常冒泡到应用程序根。我同意你所说的默认异常。我在相关的Github问题上留下了我的0.02美元。感谢您的回复和非常开放的态度。今天晚些时候我会很高兴地捡到那0.02美元。我目前在办公室,没有GitHub凭据。希望以后能见到你。
<Window x:Class="my_lights.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="AddControls" Height="114" Width="212">
    <StackPanel Name="splMain">
        <Button Click="btnAddMore_Click">Discover</Button>
    </StackPanel>
</Window>