Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/325.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C#异步/等待写入文本框_C#_Multithreading_Async Await_Backgroundworker - Fatal编程技术网

C#异步/等待写入文本框

C#异步/等待写入文本框,c#,multithreading,async-await,backgroundworker,C#,Multithreading,Async Await,Backgroundworker,不用说,我是C#新手,在学习过程中会做一些基本的事情。我试图理解异步/等待特性。我有一个带有两个文本框和一个按钮的表单。当我单击该按钮时,它会检查远程计算机的服务状态(在本例中为远程注册表)。在检查时,它会写入正在检查注册表并告诉用户等待。然后,如果状态已停止,则会启动,并获取我要查找的一些值,并将这些值写入第二个文本框 我的代码可以工作,并且我能够获得我的值。但是GUI在此期间冻结。我尝试实现backgroundworker、thread和Async/Wait,但没有成功。我尝试执行任务,但无

不用说,我是C#新手,在学习过程中会做一些基本的事情。我试图理解异步/等待特性。我有一个带有两个文本框和一个按钮的表单。当我单击该按钮时,它会检查远程计算机的服务状态(在本例中为远程注册表)。在检查时,它会写入正在检查注册表并告诉用户等待。然后,如果状态已停止,则会启动,并获取我要查找的一些值,并将这些值写入第二个文本框

我的代码可以工作,并且我能够获得我的值。但是GUI在此期间冻结。我尝试实现backgroundworker、thread和Async/Wait,但没有成功。我尝试执行任务,但无法实现

当我试图返回一个字符串,将状态和值写入文本框时,这里或其他站点上显示的所有示例都只返回int。我试图将其转换为字符串,但没有成功

长话短说,对于这种类型的流程,什么是更好的方法?有人能告诉我如何和评论什么是我更好理解的方法吗?我想学习如何做到这一点,但同时学习为什么,并学习编写更干净的代码

感谢大家提前抽出时间

string ComputerName = "Lab01";
    public frmRegChecker()
    {
        InitializeComponent();
    }


    private void Button1_Click(object sender, EventArgs e)
    {
      Check_Status();        

    }

    private void Check_Status()
    {
        TxtBoxstatus.AppendText("Checking Remote Registry service status on computer : " + ComputerName);
        TxtBoxstatus.AppendText(Environment.NewLine);
        TxtBoxstatus.AppendText("Please wait... ");

         ServiceController sc = new ServiceController("RemoteRegistry", ComputerName);
            try
            {


                TxtBoxstatus.AppendText("The Remote Registry service status is currently set to : " + sc.Status.ToString());
                TxtBoxstatus.AppendText(Environment.NewLine);


                if (sc.Status == ServiceControllerStatus.Stopped)
                {

                    // Start the service if the current status is stopped.

                    TxtBoxstatus.AppendText("Starting Remote Registry service...");
                    TxtBoxstatus.AppendText(Environment.NewLine);
                    try
                   {
                       // Start the service, and wait until its status is "Running".
                        sc.Start();
                        sc.WaitForStatus(ServiceControllerStatus.Running, new TimeSpan(0, 0, 3));
                        sc.Refresh();
                        sc.WaitForStatus(ServiceControllerStatus.Running);

                        // Display the current service status.
                        TxtBoxstatus.AppendText("The Remote Registry status is now set to:" + sc.Status.ToString());
                       richTextBox1.AppendText(Environment.NewLine);
                        try
                        {
                           var reg = RegistryKey.OpenRemoteBaseKey(RegistryHive.LocalMachine, ComputerName);
                            var key = reg.OpenSubKey(@"Software\Microsoft\Windows NT\CurrentVersion\");
                            string _OSVersion = (key.GetValue("CurrentVersion")).ToString();
                           richTextBox1.AppendText("OS version is : " + _OSVersion);
                            richTextBox1.AppendText(Environment.NewLine);
                       }
                        catch (InvalidOperationException)
                       {

                            richTextBox1.AppendText("Error getting registry value from" + ComputerName);
                            richTextBox1.AppendText(Environment.NewLine);
                        }
                    }
                    catch (InvalidOperationException)
                    {

                        richTextBox1.AppendText("Could not start the Remote Registry service.");
                        richTextBox1.AppendText(Environment.NewLine);
                    }
                }
                else if (sc.Status == ServiceControllerStatus.Running)
               {
                   try
                   {
                     var reg = RegistryKey.OpenRemoteBaseKey(RegistryHive.LocalMachine, ComputerName);
                     var key = reg.OpenSubKey(@"Software\Microsoft\Windows NT\CurrentVersion\");
                            string _OSVersion = (key.GetValue("CurrentVersion")).ToString();
                     richTextBox1.AppendText("OS version is : " + _OSVersion);
                     richTextBox1.AppendText(Environment.NewLine);
                    }
                    catch (InvalidOperationException)
                    {

                            richTextBox1.AppendText("Error getting registry value from" + ComputerName);
                            richTextBox1.AppendText(Environment.NewLine);
                    }

                }
           }

          }
          catch
           {                  
             richTextBox1.AppendText("Error getting registry value from " + ComputerName);
             richTextBox1.AppendText(Environment.NewLine);

           }
}

我认为您仍然可以使用backgroundworker在不冻结GUI的情况下使文本框显示消息。请参考此问题,了解如何从backgroundworker返回对象。

这可以使用async/Wait轻松完成。例如:

一个简单的WPF表单:

<Window x:Class="WpfApp1.MainWindow"
    ...>
  <Grid>
    <Button Name="button" Content="Start" Click="Button_Click"/>
    <TextBox Name="textButton" />
  </Grid>
</Window>

以及后面的关联代码:

public partial class MainWindow:Window
{
    public MainWindow()
    {
        InitializeComponent();
    }

    private async void Button_Click(object sender, RoutedEventArgs e)
    {                        
           textButton.Text = "Running...";
           string result = await DoIt();
           textButton.Text = result;
    }

    private async Task<string> DoIt()
    {
        await Task.Delay(3000);
        return "Finished...";
    }
}
公共部分类主窗口:窗口
{
公共主窗口()
{
初始化组件();
}
专用异步无效按钮\u单击(对象发送方,路由目标)
{                        
Text按钮。Text=“正在运行…”;
字符串结果=等待DoIt();
Text按钮。Text=结果;
}
私有异步任务DoIt()
{
等待任务。延迟(3000);
返回“完成…”;
}
}
单击该按钮时,“DoIt”中长期运行的“计算”将“异步”启动。当它运行时,UI将保持响应。 当DoIt返回其结果时(在本例中,虚拟延迟3秒后),“单击”事件处理程序继续

备注:

  • 为了简单起见,本例使用代码隐藏。该技术也可以使用MVVM模式(异步操作从命令启动)

  • “async void”是一种反模式,但用于遵守代码隐藏中自动生成的eventhandler

  • 在实际应用程序中,异步“DoIt”方法可能位于后端“模型类”中

  • 本例假设您只想在长时间运行的操作完成后更新UI。如果您想进行中间更新,有几个选项(遗憾的是,有点复杂)


不幸的是,
ServiceController
是一个相当过时的类,它本身不支持
async
/
wait
。如果可能的话,这将是最干净的解决方案

因此,您可以使用
async
/
wait
任务。运行
任务。运行
在后台线程上执行代码,您可以从UI使用
async
/
wait
来使用该后台操作。这种方法允许以自然方式传播和处理异常,并且允许自然处理返回值。为了简单起见,现在去掉文本框更新,第一步如下所示:

private async void Button1_Click(object sender, EventArgs e)
{
  try
  {
    var osVersion = await Task.Run(() => CheckStatus());
    richTextBox1.AppendText("OS version is : " + osVersion);
    richTextBox1.AppendText(Environment.NewLine);
  }
  catch (InvalidOperationException ex)
  {
    richTextBox1.AppendText("Error getting registry value from" + ComputerName);
    richTextBox1.AppendText(ex.ToString());
    richTextBox1.AppendText(Environment.NewLine);
  }
}

private string CheckStatus()
{
  ServiceController sc = new ServiceController("RemoteRegistry", ComputerName);
  if (sc.Status == ServiceControllerStatus.Stopped)
  {
    // Start the service if the current status is stopped.
    // Start the service, and wait until its status is "Running".
    sc.Start();
    sc.WaitForStatus(ServiceControllerStatus.Running, new TimeSpan(0, 0, 3));
    sc.Refresh();
    sc.WaitForStatus(ServiceControllerStatus.Running);
  }

  var reg = RegistryKey.OpenRemoteBaseKey(RegistryHive.LocalMachine, ComputerName);
  var key = reg.OpenSubKey(@"Software\Microsoft\Windows NT\CurrentVersion\");
  return (key.GetValue("CurrentVersion")).ToString();
}
private async void Button1_Click(object sender, EventArgs e)
{
  try
  {
    var progress = new Progress<string>(update =>
    {
      TxtBoxstatus.AppendText(update);
      TxtBoxstatus.AppendText(Environment.NewLine);
    });
    var osVersion = await Task.Run(() => CheckStatus(progress));
    richTextBox1.AppendText("OS version is : " + osVersion);
    richTextBox1.AppendText(Environment.NewLine);
  }
  catch (InvalidOperationException ex)
  {
    richTextBox1.AppendText("Error getting registry value from" + ComputerName);
    richTextBox1.AppendText(ex.ToString());
    richTextBox1.AppendText(Environment.NewLine);
  }
}

private string CheckStatus(IProgres<string> progress)
{
  progress?.Report("Checking Remote Registry service status on computer : " + ComputerName);
  progress?.Report("Please wait... ");

  ServiceController sc = new ServiceController("RemoteRegistry", ComputerName);
  progress?.Report("The Remote Registry service status is currently set to : " + sc.Status.ToString());
  if (sc.Status == ServiceControllerStatus.Stopped)
  {
    // Start the service if the current status is stopped.
    progress?.Report("Starting Remote Registry service...");
    // Start the service, and wait until its status is "Running".
    sc.Start();
    sc.WaitForStatus(ServiceControllerStatus.Running, new TimeSpan(0, 0, 3));
    sc.Refresh();
    sc.WaitForStatus(ServiceControllerStatus.Running);
    progress?.Report("The Remote Registry status is now set to:" + sc.Status.ToString());
  }

  var reg = RegistryKey.OpenRemoteBaseKey(RegistryHive.LocalMachine, ComputerName);
  var key = reg.OpenSubKey(@"Software\Microsoft\Windows NT\CurrentVersion\");
  return (key.GetValue("CurrentVersion")).ToString();
}
接下来,添加进度更新。这有一个内置机制-
IProgress
/
progress
,其工作原理如下:

private async void Button1_Click(object sender, EventArgs e)
{
  try
  {
    var osVersion = await Task.Run(() => CheckStatus());
    richTextBox1.AppendText("OS version is : " + osVersion);
    richTextBox1.AppendText(Environment.NewLine);
  }
  catch (InvalidOperationException ex)
  {
    richTextBox1.AppendText("Error getting registry value from" + ComputerName);
    richTextBox1.AppendText(ex.ToString());
    richTextBox1.AppendText(Environment.NewLine);
  }
}

private string CheckStatus()
{
  ServiceController sc = new ServiceController("RemoteRegistry", ComputerName);
  if (sc.Status == ServiceControllerStatus.Stopped)
  {
    // Start the service if the current status is stopped.
    // Start the service, and wait until its status is "Running".
    sc.Start();
    sc.WaitForStatus(ServiceControllerStatus.Running, new TimeSpan(0, 0, 3));
    sc.Refresh();
    sc.WaitForStatus(ServiceControllerStatus.Running);
  }

  var reg = RegistryKey.OpenRemoteBaseKey(RegistryHive.LocalMachine, ComputerName);
  var key = reg.OpenSubKey(@"Software\Microsoft\Windows NT\CurrentVersion\");
  return (key.GetValue("CurrentVersion")).ToString();
}
private async void Button1_Click(object sender, EventArgs e)
{
  try
  {
    var progress = new Progress<string>(update =>
    {
      TxtBoxstatus.AppendText(update);
      TxtBoxstatus.AppendText(Environment.NewLine);
    });
    var osVersion = await Task.Run(() => CheckStatus(progress));
    richTextBox1.AppendText("OS version is : " + osVersion);
    richTextBox1.AppendText(Environment.NewLine);
  }
  catch (InvalidOperationException ex)
  {
    richTextBox1.AppendText("Error getting registry value from" + ComputerName);
    richTextBox1.AppendText(ex.ToString());
    richTextBox1.AppendText(Environment.NewLine);
  }
}

private string CheckStatus(IProgres<string> progress)
{
  progress?.Report("Checking Remote Registry service status on computer : " + ComputerName);
  progress?.Report("Please wait... ");

  ServiceController sc = new ServiceController("RemoteRegistry", ComputerName);
  progress?.Report("The Remote Registry service status is currently set to : " + sc.Status.ToString());
  if (sc.Status == ServiceControllerStatus.Stopped)
  {
    // Start the service if the current status is stopped.
    progress?.Report("Starting Remote Registry service...");
    // Start the service, and wait until its status is "Running".
    sc.Start();
    sc.WaitForStatus(ServiceControllerStatus.Running, new TimeSpan(0, 0, 3));
    sc.Refresh();
    sc.WaitForStatus(ServiceControllerStatus.Running);
    progress?.Report("The Remote Registry status is now set to:" + sc.Status.ToString());
  }

  var reg = RegistryKey.OpenRemoteBaseKey(RegistryHive.LocalMachine, ComputerName);
  var key = reg.OpenSubKey(@"Software\Microsoft\Windows NT\CurrentVersion\");
  return (key.GetValue("CurrentVersion")).ToString();
}
private async void按钮1\u单击(对象发送方,事件参数e)
{
尝试
{
变量进度=新进度(更新=>
{
TxtBoxstatus.AppendText(更新);
TxtBoxstatus.AppendText(Environment.NewLine);
});
var osVersion=wait Task.Run(()=>CheckStatus(progress));
richTextBox1.AppendText(“操作系统版本为:”+osVersion);
richTextBox1.AppendText(Environment.NewLine);
}
捕获(无效操作异常ex)
{
richTextBox1.AppendText(“从“+ComputerName”获取注册表值时出错);
richTextBox1.AppendText(例如ToString());
richTextBox1.AppendText(Environment.NewLine);
}
}
私有字符串检查状态(IProgres进度)
{
进度?.Report(“正在检查计算机上的远程注册表服务状态:“+ComputerName”);
进度?报告(“请稍候…”);
ServiceController sc=新的ServiceController(“RemoteRegistry”,ComputerName);
progress?.Report(“远程注册表服务状态当前设置为:”+sc.status.ToString());
如果(sc.Status==ServiceControllerStatus.Stopped)
{
//如果当前状态为“已停止”,则启动服务。
进度?.Report(“正在启动远程注册表服务…”);
//启动服务,并等待其状态为“正在运行”。
sc.Start();
sc.WaitForStatus(ServiceControllerStatus.Running,新的时间跨度(0,0,3));
sc.Refresh();
sc.WaitForStatus(服务控制器Status.Running);
progress?.Report(“远程注册表状态现在设置为:”+sc.status.ToString());
}
var reg=RegistryKey.OpenRemoteBaseKey(RegistryHive.LocalMachine,ComputerName);
var key=reg.OpenSubKey(@“Software\Microsoft\Windows NT\CurrentVersion\”);
return(key.GetValue(“CurrentVersion”).ToString();
}

注意关注点的分离:唯一涉及UI对象的代码是UI事件处理程序。包含实际程序逻辑的
CheckStatus
方法与UI分离-它所知道的是它可以报告进度字符串并返回字符串结果。

后台工作人员应该为此工作,这就是job这些都是为你设计的。你遇到了什么问题