Meto
Meto

Reputation: 440

WPF Control Hosted in WinForm Blocks WinForm controls from loaded even with thread

I have WPF Control hosted in winform which have Menu and some labels. the WPF controls connect to internet to download some data. I divide the code into two steps first just set the control properties second connect to net the second runs inside thread, but Winform controls doesn't take place on the form until the WPF control finish his two steps.

I have tried many approach to make it thread-able but all ways goes to same destination.

CODE 1- Load WPF Control

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
}

Upvotes: 0

Views: 313

Answers (1)

Andy
Andy

Reputation: 30418

It looks like from the code you posted that the delay is due to running GetWeather on the UI thread. Assuming that weatherControl is an instance of the WPF control, this runs on the UI thread because that is the thread that its dispatcher belongs to.

If you want to run code on a background thread, one easy way to do so is to use a BackgroundWorker. You could use it something like this:

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();
}

The code in the DoWork event handler runs on a background thread, while the code in the RunWorkerCompleted event handler runs on the UI thread.

Upvotes: 1

Related Questions