控制台"Hangs"GUI启动时 [英] Console "Hangs" when GUI launches

查看:72
本文介绍了控制台"Hangs"GUI启动时的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在我开始之前,我想对任何...愚蠢的...表示歉意,当我问这个问题时可能会显示出来,我想从Java来之后学习C#,只是想直接跳入它!

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!

我正在开发一个旨在通过控制台接收命令的项目,例如播放蝙蝠侠开始",它将开始播放电影蝙蝠侠开始".它还需要音乐等命令.通过这种设置,我的目标是对其进行语音控制,因此我并不真正在意使用GUI而不是控制台.当我让程序播放电影时,它会加载一个没有边框,没有内容的GUI窗口,并且它使用的构造函数是:

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

MediaPlayer由主要功能控制(目前).我加载和运行视频的代码是:

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

由于我是C#的所有人,所以我可以使用GUI的方法是开始一个新的WPF项目,创建GUI并编写代码,然后将xaml和cs文件复制粘贴到我的项目中(因为我是菜鸟,对不起).也许这是导致问题的原因.

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.

此代码(通常)可以正常工作.当我运行程序时,它将加载视频文件,打开窗口,并在播放声音的同时在屏幕上播放视频.但是,当它开始播放视频时,GUI挂起"并且不接受任何输入的或"输出,但是由于光标仍在闪烁,它并未冻结.我不确定为什么会这样.

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.

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

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!

我的程序中有更多的类和内容在进行中,因此我不得不将所有这些内容放在一起,并仔细检查,所以如果我遗漏了某些东西或变得愚蠢,请告诉我,我可以修复它.由于我还是C#的新手(但对编程不是新手),我可能也错过了一些问题详细信息.

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.

我想知道解决方案是否是使其全部基于GUI,而不是基于混合控制台和GUI?由于我在网上找到的信息,这两种类型的线程之间似乎有些烦人……不符之处?

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?

无论如何,任何帮助都将是非常有用的,过去3天我一直在尝试调试它,但是没有取得任何进展.如果有帮助,请在此处链接到存储库!谢谢:)

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 :我在等待响应时进行了一些更改,主要是更改了其绘制到GUI的方式.最初,我将它绘制到背景上,但是现在通过MediaElement使它进行处理.这是我的窗口现在的整个班级:

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!

推荐答案

考虑将其转换为WPF应用程序,这将使事情变得简单.

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

无论如何,您仍然可以在不锁定控制台的情况下使用GUI,但是必须在单独的专用STA线程上执行与GUI相关的内容.由于您使用的是WPF,因此此帮助程序应该很有用(此代码不是生产质量的代码,但是可以正常工作):

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

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

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

与UI线程的所有通信均应通过 Dispatcher.Invoke() Dispatcher.BeginInvoke()方法进行.请注意,由于我们现在有多个线程,因此必须在UI线程上创建 MediaPlayer 对象.您仍然可以在所需的任何线程上保留其引用,但是对 MediaPlayer 对象的任何方法调用都必须通过 Dispatcher .

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.

要更改的内容:

  • 在尝试使用 Dispatcher 之前,先添加 UIThread.Start(); 调用. Main()方法的开头是执行此操作的好地方.
  • MediaPlayer 对象应按以下方式创建: mediaPlayer = UIThread.Dispatcher.Invoke(()=> new Media());
  • 任何与UI相关的代码都应转到 Dispatcher.Invoke() Dispatcher.BeginInvoke(): UIThread.Dispatcher.BeginInvoke(()=>; playVideo(@"C:\ video.avi"));
  • 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"));

更新

还将 new System.Windows.Application().Run(videoPanel); 更改为简单的 videoPanel.Show(). Application.Run()一直阻塞,直到关闭窗口.

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

这篇关于控制台"Hangs"GUI启动时的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆