C# 如何不阻止用户界面

C# 如何不阻止用户界面,c#,C#,我有一个应用程序,可以加载XML文件,然后将其解析为一些不同的类。 它有自己的窗口,带有类似“加载文件”的按钮 有一些原理图代码看起来像什么 ///In main window public void Button_Click () { //(VM)DataContext.AddNewFile(); } ///In VM public void AddNewFile() { //Some code with file dialogs and messages with sev

我有一个应用程序,可以加载XML文件,然后将其解析为一些不同的类。 它有自己的窗口,带有类似“加载文件”的按钮

有一些原理图代码看起来像什么

///In main window 

public void Button_Click ()
{
   //(VM)DataContext.AddNewFile();
}

///In VM

public void AddNewFile()
{
   //Some code with file dialogs and messages with several methods, one of which leads to AddMyType()
}

private void AddMyType(string file)
{
   //Creates class of myType
}

///In Type class constructor

internal MyType(string file)
{
   //Launches XML parser class to parse data from XML and create from this all MyType
   data = ParseFile(file).Result;
}

///In XML parser class:

internal async Task<MyTypeData>ParseFile(file)
{
   //Main method which launches background tasks and shows messages with progress bar 
   //Should update UI

   _progress = new Progress<int>(number =>
   {
       _message.UpdateProgress(number);
   });

   someData = await Task.Run(()=> BackgroundWorkTask(rawData, _progress));
   _message.Show(_maximumProgressValue); //Shows custom message with progress bar
   someOtherData = await Task.Run(()=> BackgroundWorkTask(otherRawData, _progress));
}

private <T> Task BackgroundWorkTask(rawData)
{
   //Some big work going here and gives some result
}

///在主窗口中
公共作废按钮\u单击()
{
//(VM)DataContext.AddNewFile();
}
///在虚拟机中
public void AddNewFile()
{
//一些带有文件对话框的代码和带有多个方法的消息,其中一个方法导致AddMyType()
}
私有void AddMyType(字符串文件)
{
//创建myType的类
}
///类型内类构造函数
内部MyType(字符串文件)
{
//启动XML解析器类,从XML解析数据,并从此类型创建所有MyType
data=ParseFile(file).Result;
}
///在XML解析器类中:
内部异步TaskParseFile(文件)
{
//启动后台任务并用进度条显示消息的主方法
//应该更新用户界面
_进度=新进度(编号=>
{
_message.UpdateProgress(编号);
});
someData=wait Task.Run(()=>BackgroundWorkTask(rawData,_progress));
_message.Show(_maximumProgressValue);//使用进度条显示自定义消息
someOtherData=wait Task.Run(()=>BackgroundWorkTask(otherRawData,_progress));
}
专用任务后台工作任务(rawData)
{
//一些大的工作在这里进行,并给出了一些结果
}
问题是UI冻结了

我尝试了许多变体:

Task.Wait(),Wait BackgroundWorkTask并使用

private <T> Task BackgroundWorkTask()
{
   //Freezes
   while(true){} 
   Task.Delay(x)
   Task.Delay(x).Wait()
   Thread.Sleep(x)
   and await Task.Delay(x) (if private async Task)
}
private Task BackgroundWorkTask()
{
//冻结
while(true){}
任务延迟(x)
Task.Delay(x.Wait())
线程。睡眠(x)
和等待任务。延迟(x)(如果是专用异步任务)
}
我猜这是因为之前所有的主要工作都是在主线程中以同步模式进行的。但在启动ParseFile()方法之前,我对主线程中的数据有很多不同的操作

据我所知,异步方法使用wait Task.Run(()=>);用于在其他线程上执行某些工作,不应阻止UI

我认为使用异步方法更新UI以等待不同的任务会有所帮助,但是


如果有解决此问题的方法?

使用
结果
会阻塞您的UI线程,并且由于您无法使用
异步
构造函数,您需要探索一种替代方法,其中有许多:

  • 将数据而不是文件路径传递给构造函数:

    private async Task AddMyType(string file)
    {
       var data = await ParseFile(file);
       var myType = new MyType(data);
    }
    
    ///In Type class constructor
    
    internal MyType(Data data)
    {
        this.data = data;
    }
    

  • MyType
    中使用
    async
    工厂方法:

    class MyType
    {
        private MyType(Data data)
        {
            this.data = data;
        }
    
        internal static async Task<MyType> CreateAsync(string file)
        {
            var data = await ParseFile(file);
            return new MyType(data);
        }
    }
    

  • 您编写了
    ParseFile(file.Result)。它会阻止构造函数的执行,直到ParseFile方法完成。指导原则:总是
    等待
    方法调用返回
    任务
    ,因此只能从返回任务本身的
    异步
    方法调用它们(可以是
    异步无效的事件处理程序除外)关于带有文件解析代码的构造函数,您可能违反了OOP原则,请检查,非常感谢!我将检查您的所有建议并分享结果。Thx获取有关构造函数的信息。非常感谢!那真的很有帮助!
    
    class MyType
    {
        Task<Data> dataTask;
    
        internal MyType(string file)
        {
            dataTask = ParseFile(file);
        }
    
        public async Task MethodThatUsesData()
        {
            var data = await dataTask;
            // Use data..
        }
    }