0

メニューといくつかのラベルを持つwinformでホストされているWPFコントロールがあります。WPF コントロールはインターネットに接続してデータをダウンロードします。コードを 2 つのステップに分割します。最初にコントロール プロパティを設定し、2 番目の接続をスレッド内で実行しますが、WPF コントロールが 2 つのステップを完了するまで、Winform コントロールはフォーム上で実行されません。

私はそれをスレッド化できるようにするために多くのアプローチを試みましたが、すべての方法が同じ宛先に行きます。

コード 1 - WPF コントロールのロード

private void MDI_Load(object sender, EventArgs e)
    {
        MenuManager.FillMenu(MainMenu); // I have filled WinForm Menu first, but it doesn't appear until WPF finish

        #region = WPF Control =

        wpfManager.AddweatherControl();
        wpfManager.weatherManager.Start(); // This have to run in another thread

        #endregion
}

2- wpfManager.weatherManager.Start

    public void Start()
{
    //var tsk = System.Threading.Tasks.Task.Factory.StartNew(GetWeather);
    //tsk.ContinueWith(t => { MessageBox.Show(t.Exception.InnerException.Message); },
    //   System.Threading.CancellationToken.None, System.Threading.Tasks.TaskContinuationOptions.OnlyOnFaulted,
    //   System.Threading.Tasks.TaskScheduler.FromCurrentSynchronizationContext());

    //System.Threading.Thread t = new System.Threading.Thread(
    //    () => weatherControl.Dispatcher.BeginInvoke(DispatcherPriority.Normal, new Action(GetWeather))
    //    );
    //t.SetApartmentState(System.Threading.ApartmentState.STA);
    //t.Start();

    weatherControl.Dispatcher.BeginInvoke(new Action(GetWeather), new object[] { });
}

void GetWeather()
{
    #region = Weather =
    Yweather.Getweather(UserManager.CurrentUser.Preferences.WeatherCity);

    if (Yweather.Online && Yweather.IDayForecast.Count > 0)
    {
        weatherControl.CurrentDegree.Text = Yweather.IDayForecast[0].CurrentTemperature.ToString();
        weatherControl.WeatherTypeName.Text = Yweather.IDayForecast[1].WeatherText;
        weatherControl.AllDayDegree.Text = Yweather.IDayForecast[1].LowTemperature + " - " + Yweather.IDayForecast[1].HighTemperature;
        weatherControl.WeatherType.Source = wpfManager.BitmapToImageSource(Yweather.IDayForecast[0].Image);

        xWeatherDay weatherday1 = weatherControl.OhterDaysPanel.Children[0] as xWeatherDay;
        weatherday1.AllDayDegree.Text = Yweather.IDayForecast[2].LowTemperature + " - " + Yweather.IDayForecast[2].HighTemperature;
        weatherday1.WeatherType.Source = wpfManager.BitmapToImageSource(Yweather.IDayForecast[2].Image);
    }
    else
    {
        weatherControl.CurrentDegree.Text = "0";
        weatherControl.WeatherTypeName.Text = "NAN";
        weatherControl.AllDayDegree.Text = "0 - 0";
        weatherControl.WeatherType.Source = wpfManager.BitmapToImageSource(Yweather.OfflineImage);
    }

    #endregion
}
4

1 に答える 1

1

投稿したコードから、遅延はGetWeatherUI スレッドで実行されていることが原因のようです。これが WPF コントロールのインスタンスであると仮定するとweatherControl、これは UI スレッドで実行されます。これは、UI スレッドがそのディスパッチャーが属するスレッドであるためです。

バックグラウンド スレッドでコードを実行する場合、簡単な方法の 1 つはBackgroundWorkerを使用することです。次のように使用できます。

public void Start()
{
    var worker = new BackgroundWorker();
    worker.DoWork += (sender, args) =>
    {
        GetWeather();
        // put the results of getting the weather in to args.Result
    };
    worker.RunWorkerCompleted += (sender, args) =>
    {
        // use args.Result to update the UI
    };
    worker.RunWorkerAsync();
}

イベント ハンドラーのコードはDoWorkバックグラウンド スレッドで実行されますが、RunWorkerCompletedイベント ハンドラーのコードは UI スレッドで実行されます。

于 2013-05-28T23:35:12.103 に答える