控制台"挂起" GUI启动时

时间:2015-05-29 22:27:46

标签: c# wpf user-interface console hang

在开始之前,我想为任何......白痴而道歉......在提出这个问题时我可能会表现出来,我是在尝试从Java学习C#后想到的,只是想要跳进去吧!

我正在开发一个旨在通过控制台接收命令的项目,例如"玩蝙蝠侠开始"它将开始播放电影Batman Begins。它还需要音乐等命令。通过这种设置,我的目标是让它受语音控制,所以我并不真正关心使用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天我一直试图调试这个并且没有取得任何进展。如果有帮助,就会有一个指向回购here的链接!谢谢:))

编辑:我在等待响应时做了一些更改,主要是改变它绘制到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;
        }
    }

这并没有修复控制台挂起,但是这使得所有内容更加集中化,从而使调试更容易。希望这可能有所帮助!

1 个答案:

答案 0 :(得分:1)

考虑将其转换为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

要改变的事情:

  • 在尝试使用UIThread.Start();之前添加Dispatcher来电。 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()阻止,直到窗口关闭。