PulsePanda
PulsePanda

Reputation: 1856

Console "Hangs" when GUI launches

Before I start, I'd like to appologize for any... idiocy... that I may show when asking this question, I'm trying to learn C# after coming from Java, and just wanted to jump right into it!

I'm working on a project that is designed to take commands through the console, such as "play batman begins" and it'll start playing the movie Batman Begins. It also takes commands for music, etc. With this setup, my goal is to have it voice controlled, so I'm not really concerned with using a GUI instead of the console. When I have the program play a movie, it loads up a GUI window with no border, no content, and the constructor that it uses is:

public MainWindow(MediaPlayer player)
{
     InitializeComponent();
     VideoDrawing drawing = new VideoDrawing { Rect = new Rect(0, 0, 800, 600), Player = player };
     DrawingBrush brush = new DrawingBrush(drawing);
     Background = brush;
}

The MediaPlayer is controlled from the main function (for now). My code to load the video and run it is:

MediaPlayer mp = new MediaPlayer();
mp.Open(new Uri("C:\\test.mp4", UriKind.RelativeOrAbsolute));

VideoDrawing vidDrawing = new VideoDrawing();
vidDrawing.Rect = new Rect(0, 0, 100, 100);
vidDrawing.Player = mp;

DrawingBrush DBrush = new DrawingBrush(vidDrawing);
videoPanel = new MainWindow(mp); // GUI panel to play the video on, constructor is listed above

play();
new System.Windows.Application().Run(videoPanel);

As I'm new to C# and all, the way I got the GUI to work with this is by starting a new WPF project, creating the GUI and writing the code, then copy paste the xaml and cs files into my project (cause I'm a noob, I'm sorry). MAYBE this is causing the problem.

This code works (mostly) fine. When I run my program, it loads the video file, opens the Window, and plays the video on the screen while playing the sound too. However, when it starts the video, the GUI "hangs" and doesnt accept any input's OR outputs, but it's not frozen as the cursor is still flashing. I'm not sure why this is.

I've tried threading almost anything I can think of, but I get errors with that. I've tried localizing the loading to the GUI window itself, however it still hangs the console. I've been searching online for all sorts of things for the past few days and cant find a solution, so I turned here!

My program has a lot more classes and stuff going on, so I had to throw all this stuff together, and double check, so if I'm missing something or made a stupid please let me know and I can fix it. As I'm still kinda new to C# (but not new to programming) I may have missed something in my question details as well.

I'm wondering if the solution is to make it ALL GUI based, instead of hybrid console and GUI? Because of the information I've found online it looks like there can be some annoying... discrepancies... between the two types of threads?

Anyway, any help would be great, I've spent the past 3 days trying to debug this and haven't made any progress. If it helps, there's a link to the repo here! Thanks :)

EDIT: I made some changes while waiting for a response, primarily changing the way it draws to the GUI. Originally I had it painting to the background, but now have made it handle through a MediaElement. This is the whole class for my window now:

public partial class MainWindow : Window
    {

        public MainWindow(string dir)
        {
            InitializeComponent();

            video.Source = new Uri(dir); //video is the name of my MediaElement
        }

        public void pause(){
            video.Pause();
        }

        public void resume()
        {
            video.Play();
        }

        public void stop()
        {
            video.Stop();
            this.Close();
        }

        public void volume(int i)
        {
            video.Volume = i;
        }
    }

This did NOT fix the console Hang, however this made everything much more centralized so as to make debugging easier. Hope this may help!

Upvotes: 2

Views: 269

Answers (1)

max
max

Reputation: 34417

Consider converting this to a WPF-application, it will make things easier.

Anyway, you can still work with GUI without locking console, but you must execute GUI-related stuff on a separate dedicated STA thread. Since you are using WPF, this helper should be useful (this code is not production-quality, but works):

static class UIThread
{
    private static Dispatcher _dispatcher;

    public static void Start()
    {
        using(var wh = new ManualResetEvent(false))
        {
            var thread = new Thread(ThreadProc)
            {
                IsBackground = true,
            };
            thread.SetApartmentState(ApartmentState.STA);
            thread.Start(wh);
            wh.WaitOne();
        }
    }

    private static void ThreadProc(object arg)
    {
        var wh = (EventWaitHandle)arg;
        _dispatcher = Dispatcher.CurrentDispatcher;
        wh.Set();
        Dispatcher.Run();
    }

    public static Dispatcher Dispatcher
    {
        get { return _dispatcher; }
    }
}

This helper provides you with a reference to a Dispatcher object, which is used to execute methods on UI thread.

All communication with UI thread should be done through Dispatcher.Invoke() or Dispatcher.BeginInvoke() methods. Note that since we now have several threads, MediaPlayer objects must be created on the UI thread. You can still hold it's reference on any thread you want, but any method calls to MediaPlayer object must go through Dispatcher.

Things to change:

  • add a UIThread.Start(); call before any attempts to use Dispatcher. Beginning of Main() method is a good place to do this.
  • MediaPlayer objects should be created like this: mediaPlayer = UIThread.Dispatcher.Invoke(() => new Media());
  • any UI-related code should go to Dispatcher.Invoke() or Dispatcher.BeginInvoke(): UIThread.Dispatcher.BeginInvoke(() => playVideo(@"C:\video.avi"));

Update

Also change new System.Windows.Application().Run(videoPanel); to simple videoPanel.Show(). Application.Run() blocks until the window is closed.

Upvotes: 1

Related Questions