C# 正在从Winform调用Bing映射的WPF窗口

C# 正在从Winform调用Bing映射的WPF窗口,c#,wpf,multithreading,winforms,bing-maps,C#,Wpf,Multithreading,Winforms,Bing Maps,我正在开发一个Windows窗体,它将获取用户的纬度和经度,执行一些长时间的计算,并在地图上显示用户的位置和一些路线。地图将使用Bing Maps API显示在单独的WPF窗口中。由于在用户输入纬度和经度后需要执行的计算非常复杂,需要花费大量时间,因此我需要在后台线程中执行这些计算,并从该后台线程调用新的WPF窗口 起初,由于线程相关性,我无法从后台线程打开WPF窗口,但在将线程的单元状态设置为ApartmentState.STA后,我修复了它。以下是在用户输入纬度和经度并按下Winform上的

我正在开发一个Windows窗体,它将获取用户的纬度和经度,执行一些长时间的计算,并在地图上显示用户的位置和一些路线。地图将使用Bing Maps API显示在单独的WPF窗口中。由于在用户输入纬度和经度后需要执行的计算非常复杂,需要花费大量时间,因此我需要在后台线程中执行这些计算,并从该后台线程调用新的WPF窗口

起初,由于线程相关性,我无法从后台线程打开WPF窗口,但在将线程的单元状态设置为ApartmentState.STA后,我修复了它。以下是在用户输入纬度和经度并按下Winform上的按钮后调用的过程:

private void button1_Click(object sender, EventArgs e)
{
    Thread t1 = new Thread(foo);
    t1.SetApartmentState(ApartmentState.STA);
    t1.IsBackground = true;
    t1.Start();
}
线程启动时执行的过程是foo。我在论坛上读到,我需要调用System.Windows.Threading.Dispatcher.Run,以便线程完成后WPF窗口不会立即关闭:

private void foo()
{
    MainWindow window = new MainWindow(lat.Text, lon.Text);
    window.Show();
    window.Closed += (sender2, e2) => window.Dispatcher.InvokeShutdown();
    System.Windows.Threading.Dispatcher.Run();
}
WPF窗口称为MainWindow。代码如下:

public partial class MainWindow : Window
{
    public MainWindow(double latitude, double longitude)
    {
        InitializeComponent();

        myMap123.Focus();

        //Set the map mode to Aerial with labels
        myMap123.Mode = new AerialMode(true);
    }
}
最后,如果有些人需要WPF窗口的xaml文件,请参阅:

<Window x:Class="WPFTestApplication.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
    xmlns:m="clr-namespace:Microsoft.Maps.MapControl.WPF;assembly=Microsoft.Maps.MapControl.WPF" 
    Title="MainWindow" Height="350" Width="525">
    <Grid>
        <m:Map CredentialsProvider="KEY" x:Name="myMap123"/>
    </Grid>
</Window>
当我输入一些纬度和经度并按下按钮时,WPF窗口确实会出现,但Bing地图不会显示世界地图。相反,背景是灰色的,如果我尝试缩放或更改窗口大小,将抛出System.NullReferenceException对象引用未设置为对象实例。调试器告诉我在System.Windows.Threading.Dispatcher.Run;行中引发异常;。但是,如果我不尝试将地图居中,也不将地图设置为空中模式,则一切正常。我应该怎么做才能从后台线程调用WPF窗口并在运行时更改Bing地图的属性而不会出现任何问题? 我已经检查过,如果从主UI线程调用WPF窗口,一切都会正常工作。
有趣的是,如果我关闭WPF窗口并再次按下按钮,新的WPF窗口将正常显示Bing映射,并且不会抛出System.NullReferenceException。

我最终调用了一个UI元素。它允许我创建一个创建该UI元素的线程来执行作为参数传递的函数。

为什么要在新线程中显示新窗口?为什么不在创建新窗口时通过Dispatcher调用主WPF UI线程呢?那么,主线程如何知道后台线程何时完成了计算呢?这难道不需要用户在后台线程完成后按其他按钮来显示地图吗?这取决于地图对象。但最坏的情况是,您在后台线程上运行计算操作,即通过Task,然后在操作完成后,使用Dispatcher.Invoke通知主线程。不幸的是,您的代码示例实际上并没有显示此计算操作是如何发生的,因此不可能以特定的方式回答。