0

I have recently made a Class Library (dll) for my other project to program a Bluetooth device via serial port (COM). The library is used to transfer firmware via COM port. It works fine until the requirement comes, which requires a WPF window to show the progress of programming. I have successfully created the progress bar using standard WPF app template. However, the standard WPF does not allow me to generate dll. After searching here, I found this link that teaches you how to add a WPF window to existing Class Library project. Also, someone teaches you how to show the window from here. Everything look good until I tried, there is nothing shows up when I call the method ProgrammBluetooth() from LabVIEW.

My main method, which is in a separate .cs file:

namespace BTMProg
{
public class BTMProgrammer
{
    private bool _uut1Status = false;
    private string _uut1Message = "";

    public bool UUT1Status
    {
        get { return _uut1Status; }
        set { _uut1Status = value; }
    }

    public string UUT1Message
    {
        get { return _uut1Message; }
        set { _uut1Message = value; }
    }

    public void ProgramBluetooth (string ioPort, string firmwareFile)
    {
        List<UUT> uutList = new List<UUT>(); 
        uutList.Add(new UUT(ioPort, "UUT1", 1));

        Thread thread = new Thread(() =>
        {
            var wn = new MainWindow(uutList, firmwareFile);
            wn.ShowDialog();
            wn.Closed += (s, e) => wn.Dispatcher.InvokeShutdown();
            Dispatcher.Run();
            if (wn.TaskList[0].Result.ToUpper().Contains("SUCCESS"))
            {
                _uut1Status = true;
                _uut1Message = wn.TaskList[0].Result;
            }
            else
            {
                _uut1Status = false;
                _uut1Message = wn.TaskList[0].Result;
            }
        });

        thread.SetApartmentState(ApartmentState.STA);
        thread.Start();
    }
}
}

My WPF code in MainWindow.xaml.cs:

 ProgrammingViewModel _pvm = new ProgrammingViewModel();
 private List<string> _viewModeList = new List<string>();
 private List<Task<string>> _taskList = new List<Task<string>>();

 public List<Task<string>> TaskList {
     get => _taskList;
     set => _taskList = value;
 }

 public MainWindow(List<UUT> uutList, string firmwareFile)
 {
     InitializeComponent();
     foreach (var uut in uutList)
     {
         _viewModeList.Add(uut.UutName);
     }
     _pvm.AddProcessViewModels(_viewModeList);
     ProgressBarView.DataContext = _pvm.ProcessModels;
     StartProgramming(uutList, firmwareFile);
     Application.Current.MainWindow.Close();
  }

The issue before was that if I don't use dispatcher to create a new thread, an exception saying "The calling thread must be STA, because many UI components require this...." thrown. After I use the new thread, no error but the window does not show up as expected. What could be the problem? Thanks.

Gengjun Wu
  • 311
  • 3
  • 6

1 Answers1

0

The ShowDialog function will stop execution of the thread until the window closes, meaning the rest of that code may not run and the dispatcher may not be started. You should try the Show method instead, which returns as soon as the window is shown.

Also, what is going on with these lines in the constructor of the window?

StartProgramming(uutList, firmwareFile);
Application.Current.MainWindow.Close();

Whatever that first line does, it needs to return and not do a bunch of work if you want the window to finish getting constructed. The second line makes no sense at all. Why are you closing the main window of the application? Did you even set and open a window associated with that property at some point?

I suspect one or more of these things is preventing the thread from ever reaching the point where it can show the window.

Xavier
  • 3,254
  • 15
  • 22
  • I guess this is the reason why it does not work, the constructor did not finish then there will not be an window. I did not know that. I will try to fix it. Thank you. – Gengjun Wu Apr 12 '18 at 01:05