Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/303.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

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/wpf/12.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#_Wpf_Multithreading_Datagrid - Fatal编程技术网

C# 如何运行方法以及在方法运行时保持我的应用程序运行(不要等待方法完成她的工作)

C# 如何运行方法以及在方法运行时保持我的应用程序运行(不要等待方法完成她的工作),c#,wpf,multithreading,datagrid,C#,Wpf,Multithreading,Datagrid,我正在开发小型C应用程序,该应用程序在主屏幕上有一个DataGrid,其中包含项目,该应用程序有一个用途:当用户按F9键时,它将循环遍历DataGrid项目,并将DataGrid中的项目写入记事本,然后将该记事本发送到财政打印机,这意味着将该记事本文件放入打印机正在侦听的路径。*说明什么是财政打印机:这是一台小型打印机,它正在某个位置等待记事本文件,例如C:\MyFiles,如果您给他正确的文件,他将继续打印->这意味着带有项目的纸张将从打印机、价格、项目标题等处打印出来,打印机将把自己的文件放

我正在开发小型C应用程序,该应用程序在主屏幕上有一个DataGrid,其中包含项目,该应用程序有一个用途:当用户按F9键时,它将循环遍历DataGrid项目,并将DataGrid中的项目写入记事本,然后将该记事本发送到财政打印机,这意味着将该记事本文件放入打印机正在侦听的路径。*说明什么是财政打印机:这是一台小型打印机,它正在某个位置等待记事本文件,例如C:\MyFiles,如果您给他正确的文件,他将继续打印->这意味着带有项目的纸张将从打印机、价格、项目标题等处打印出来,打印机将把自己的文件放在他说的地方,一切正常,打印机也会在那个里写一个特殊的数字,叫做财政数字ID*,现在让我们回到C代码

所以我做了一切,一切都很好,但有一个问题:

当我在打印机正在侦听的文件夹中保留正确的文件时,打印机将接收该文件,并且我的应用程序将继续侦听打印机的文件,因为应用程序必须从打印机文件中读取该会计编号ID

我的问题来了,因为应用程序必须侦听打印机的应答,并读取其文件以将会计编号ID放入数据库等,这需要很多时间,比如3-4秒,所以在发生这种情况时,不可能单击我的应用程序或smth上的任何位置,它只是冻结

所以我的问题是,我怎样才能把这个方法放在一个线程或其他东西中,这样它就可以在我的应用程序仍然对用户的点击/请求做出响应的情况下完成她的工作

以下是用户按F9时的代码:

 if (e.Key == Key.F9)
            {
                try
                {

                        if (dtgStavke.Items.Count > 0)
                        {
                            Printer printer = new Printer();
                            printer.AdressAnswer = "C:\\MyPrinterFiles\\";
                            printer.AdressError = "C:\\MyPrinterFiles\\Errors\\";
                            printer.AdressExit = "C:\\MyPrinterFiles\\Good\\";


                            Bill newBill = new Bill();

                            newBill.OrdinalNumber = Convert.ToInt32(BillController.Instance.GetNextBillOrdinalNumber())+1;
                            newBill.Reversed = false;
                            newBill.Fiscalized = false; 
                            newBill.BFF = 0;
                            newBill.BRR = 0;

                            newBill.TotalAmount = stavkeTemp.Sum(x => (x.Price*x.Quantity));
                            newBill.TotalWithoutTax = totalWithoutTAXGlobal;
                            newBill.TotalTax = totalTaxGlobal;

                            if (_globalCustomer != null)
                            {
                                if (_globalCustomer.Status == 1)
                                {
                                    newBill.CompanyId = _globalCustomer.Id;
                                }
                                else
                                    newBill.PersonId = _globalCustomer.Id;
                            }
                            else
                            {
                                newBill.CompanyId = 1;
                                newBill.PersonId = 1;
                                newBill.UserId=1;
                            }
                            Bill lastInsertedBill = BillController.Instance.Save(newBill);
                            }

                            bool succeed = Print(lastInsertedBill, p, printer, _globalCustomer, false);
                        }

                    }

                }
                catch (Exception ex)
                {
                    MessageBox.Show(ex.Message);
                }
            }
        }
我怎么能把它隔离到一个新的线程或类似的东西,我尝试了一些事情,但它肯定不起作用

有打印方法,一切都在那里发生:

档案制作

正在等待应答以读取打印机文件

再次使用该打印机文件中的财政打印机id更新数据库

所以必须在那个里进行工作,所以以某种方式隔离它会很好,以使我的应用程序在打印方法执行其工作时对用户请求做出响应

bool succeed = Print(lastInsertedBill, p, printer, _globalCustomer, false);
谢谢各位
干杯

简单的答案是,如果您可以像前面提到的Sparrow一样使用async Wait

调用Print之后将如下所示:

bool succeed = await Task.Run(()=>Print(lastInsertedBill, p, printer, _globalCustomer, false)).ConfigureAwait(false);
public void KeyPressed(Object o, KeyPressEventArgs e)
public async Task KeyPressed(Object o, KeyPressEventArgs e)
整个代码构造所在的代码的方法签名也必须更改。想象一下,您当前的签名如下所示:

bool succeed = await Task.Run(()=>Print(lastInsertedBill, p, printer, _globalCustomer, false)).ConfigureAwait(false);
public void KeyPressed(Object o, KeyPressEventArgs e)
public async Task KeyPressed(Object o, KeyPressEventArgs e)
它应该更改为以后的样子,如下所示:

bool succeed = await Task.Run(()=>Print(lastInsertedBill, p, printer, _globalCustomer, false)).ConfigureAwait(false);
public void KeyPressed(Object o, KeyPressEventArgs e)
public async Task KeyPressed(Object o, KeyPressEventArgs e)
这些更改将使您的打印方法在不同的任务中运行,简单地说,这是利用其他线程的更有效的方法。因此,通过这种方式,当另一个后台线程执行打印任务时,您的UI线程可以自由地执行任务


如果您想了解async Wait,我建议您从这里开始。Alex Davies的一本书《C 5.0中的异步》对我的异步等待有很大帮助。它只有108页,写得非常好,您可以获得所需的所有知识。

您需要阅读async await inC@Sparrow这有点像线程,我现在肯定会读到异步编程不同于多线程,但是它是为你想做什么而设计的。@Roxy'Pro-你想要一个不从非UI线程访问UI元素的例子吗?@Roxy'Pro-这很简单。对UI元素的所有访问都必须发生在UI线程上。如果启动新线程或任务,则无法访问任何UI元素。因此,在对另一个线程执行任何处理之前,必须将所有要使用的数据提取到某种不涉及任何UI元素的数据结构中,对其进行处理,然后通过.Invoke在另一个数据结构中返回结果。。。调用UI元素以允许数据更新UI。我明天将尝试此操作,我生病了,所以对此无能为力,运行新任务怎么样?Task.Factory.StartNew=>。。。我看到很多人都在用它?这与async await?Task.Factory.StartNew相同,它是启动新任务的初始和唯一方法。但是随着.NET4.5的出现,一种新的开始新任务的方式出现了,那就是Task.Run。简单地说,Task.Run是Task.Factory.StartNew的重载,它处理创建新任务的最常见情况。更多信息:它们和您用async和await提供的解决方案有什么不同?我已经用简单的方式解释过了。关于他们差异的更多详细信息,请参阅我提到的博客文章。正如您在我的回答中所看到的:我利用了Task.Run将打印方法的工作负载传递给一个单独的任务。async关键字告诉编译器某个方法是异步方法,await关键字告诉编译器仅在后台任务完成其工作后才执行在其下编写的代码。