确保GUI没有被传入消息锁定

时间:2019-06-06 18:14:25

标签: c# wpf user-interface

我有一个UserControl,它是按照MVVM模式构建的,具有供其他应用程序发送“命令”以供控件执行的公开功能。在这种情况下,命令为strings。我试图找到一种在短时间内发送大量命令时阻止GUI挂起的方法。每个命令都应等待最后一个命令完成。

这些命令大多数都可以在显示在主控件视图中的第三方地图控件上使用。

流程如下:

  1. 应用将命令字符串发送给控件。
  2. 控件调用解析函数来解析字符串。
  3. 解析完成后,根据命令调用特定的类。
  4. 发生事情,即创建模型,更新ObservableCollection,更新地图控件等。

这是一个例子:

用户控件:

///The code behind for the control
public partial class MainControl : UserControl
{
    public MainControl()
    {
        InitializeComponent();
    }

    //Other apps call this function
    public void ExecuteCommand(string command)
    {
        CommandParser.StartParse(command);
    }
}

用于解析命令的类:

//Handles parsing a string command and calling the right class
public static class CommandParser
{
    public static void StartParse(string command)
    {
        //parses the command into a string array to hold different parts
        DoCommand(parsedCommand);
    }  

    private static void DoCommand(string[] command)
    {
        switch(command[0])
        {
            case "addpoint":
                AddCommand.AddObj(command);
                break;
            case "createstyle":
                CreateCommand.CreateObj(command);
                break;
        }
    }
}

两个采用已解析命令并执行某些操作的类:

//Adds objects to the third party map control
public static class AddCommand
{
    public static void AddObj(string[] command)
    {
        //Adds a point to the third party map control
        MapControl.AddPoint(new Point(90, -90)); //just an example
    }
}

//Creates model objects to add to observablecollections in viewmodels
public static class CreateCommand
{
    public static void CreateObj(string[] command)
    {
        //create a model
        //get the correct viewmodel
        viewModel.StylesCollection.Add(styleModel); //StylesCollection is an ObservableCollection
    }
}

非常基本的示例,但应显示所有内容的流程。因此,想象得到几千个命令。创建模型的速度很快,但是由于每次都会更新地图控件(它是GUI的一部分),或者正在修改ObservableCollection(绑定了控件的itemsource),因此GUI会在以下情况时挂起接收并执行所有这些命令。

1 个答案:

答案 0 :(得分:0)

在(很可能不太可能)的情况下,可以通过UI线程完成大量工作,您可以实现多线程。这样做的一种非常基本的方法。

首先,创建一个新线程以运行:

var task = new Thread(YourTask);
task.Start();

然后在完成计算的线程方法中,通过调用Dispatcher.Invoke将结果委托给UI线程。确保您调用电话的次数不要太频繁(例如,每秒调用次数不超过10次),因为这会再次阻塞UI线程。

public void YourTask()
{
    // do calculations and get results

    Application.Current.Dispatcher.Invoke(
        new Action(() =>
        {
            // update the UI
        }));
}