控制台”;Hangs”;当GUI启动时

本文关键字:启动 GUI Hangs 控制台 | 更新日期: 2023-09-27 17:51:07

在开始之前,我想为任何。。。白痴。。。当我问这个问题时,我可能会表现出,我从Java毕业后正在努力学习C#,只是想直接投入其中!

我正在做一个项目,该项目旨在通过控制台接收命令,比如"玩蝙蝠侠开始",它将开始播放电影《蝙蝠侠开始》。它还需要音乐等命令。通过这种设置,我的目标是对其进行语音控制,所以我并不真正关心使用GUI而不是控制台。当我让程序播放电影时,它加载一个没有边界、没有内容的GUI窗口,它使用的构造函数是:

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

MediaPlayer由主功能控制(目前(。我加载视频并运行它的代码是:

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

由于我是C#的新手,我使用GUI的方法是启动一个新的WPF项目,创建GUI并编写代码,然后将xaml和cs文件复制粘贴到我的项目中(因为我是个傻瓜,很抱歉(。也许这就是问题的根源。

这段代码(大部分(运行良好。当我运行程序时,它会加载视频文件,打开窗口,并在屏幕上播放视频,同时播放声音。然而,当它启动视频时,GUI"挂起",不接受任何输入的OR输出,但由于光标仍在闪烁,它没有被冻结。我不知道为什么会这样。

我试过线程化我能想到的几乎所有东西,但我在这方面遇到了错误。我已经尝试将加载本地化到GUI窗口本身,但是它仍然挂起控制台。在过去的几天里,我一直在网上搜索各种各样的东西,但找不到解决方案,所以我转向了这里!

我的程序有更多的类和内容,所以我不得不把所有这些东西放在一起,仔细检查,所以如果我遗漏了什么或做了一个愚蠢的事情,请告诉我,我可以修复它。因为我对C#还是一个新手(但对编程不是新手(,我可能在问题细节中也遗漏了一些东西。

我想知道解决方案是否是让它完全基于GUI,而不是混合控制台和GUI?由于我在网上找到的信息,看起来可能会有一些烦人的。。。差异。。。在两种类型的线程之间?

不管怎样,任何帮助都会很好,我在过去的3天里一直在尝试调试,但没有取得任何进展。如果有帮助的话,这里有一个回购链接!谢谢:(

EDIT:我在等待响应时做了一些更改,主要是更改了它绘制到GUI的方式。最初我把它画在背景上,但现在已经通过MediaElement处理了。这是我窗口的全部课程:

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

这并没有解决控制台挂起的问题,但这使一切更加集中,从而使调试更加容易。希望这能有所帮助!

控制台”;Hangs”;当GUI启动时

考虑将其转换为WPF应用程序,这将使事情变得更容易。

无论如何,您仍然可以在不锁定控制台的情况下使用GUI,但必须在单独的专用STA线程上执行与GUI相关的内容。由于您使用的是WPF,这个助手应该是有用的(这个代码不是生产质量,但有效(:

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

此帮助程序为您提供了对Dispatcher对象的引用,该对象用于在UI线程上执行方法。

所有与UI线程的通信都应该通过Dispatcher.Invoke()Dispatcher.BeginInvoke()方法来完成。注意,由于我们现在有几个线程,所以必须在UI线程上创建MediaPlayer对象。您仍然可以在任何需要的线程上保留它的引用,但对MediaPlayer对象的任何方法调用都必须经过Dispatcher

需要改变的事情:

  • 在尝试使用Dispatcher之前添加一个UIThread.Start();调用。Main()方法的开始是一个很好的地方
  • MediaPlayer对象应该这样创建:mediaPlayer = UIThread.Dispatcher.Invoke(() => new Media());
  • 任何与UI相关的代码都应该转到Dispatcher.Invoke()Dispatcher.BeginInvoke():UIThread.Dispatcher.BeginInvoke(() => playVideo(@"C:'video.avi"));

更新

同时将new System.Windows.Application().Run(videoPanel);更改为简单videoPanel.Show()Application.Run()阻塞直到窗口关闭。