C# 与BackgroundWorker不同的异步更新状态的替代方法
我正在开发一些在服务器端进行计算的软件。我曾尝试使用BackgroundWorker,在我尝试从胖客户机切换到web服务之前,它工作得非常好。发生了错误(我已经预料到了,因为我的同事告诉我)“BackgroundWorker未标记为可序列化”。我的应用程序的目标是用计算的进度以及当前正在计算的记录的名称更新客户端。如果需要,我可以发布一些代码,但在这种情况下,我怀疑它是否真的与问题相关。我试图实现的计划可以如下所示:C# 与BackgroundWorker不同的异步更新状态的替代方法,c#,web-services,asynchronous,backgroundworker,updating,C#,Web Services,Asynchronous,Backgroundworker,Updating,我正在开发一些在服务器端进行计算的软件。我曾尝试使用BackgroundWorker,在我尝试从胖客户机切换到web服务之前,它工作得非常好。发生了错误(我已经预料到了,因为我的同事告诉我)“BackgroundWorker未标记为可序列化”。我的应用程序的目标是用计算的进度以及当前正在计算的记录的名称更新客户端。如果需要,我可以发布一些代码,但在这种情况下,我怀疑它是否真的与问题相关。我试图实现的计划可以如下所示: 客户点击“准备”按钮 服务器接到呼叫 服务器发送数据 客户收到记录列表进行确
- 客户点击“准备”按钮
- 服务器接到呼叫
- 服务器发送数据
- 客户收到记录列表进行确认
- 客户端确认他们的选择(然后我设置后台工作程序并将其发送到服务器)
- 服务器获取调用(接收后台工作人员的引用,以及一次计算所需的所有记录)
- 通过循环我运行记录(每次计算大约需要1-3秒),更新BackgroundWorker的状态,如下所示:
另外,我没有从服务器发回太多的数据(实际上我甚至可以尝试发送更少的数据,比如只发送id),所以我认为这不会是过载的问题。基本上,当您为web编写代码时,您处理的是一个完全不同的模型,基于请求/响应,而不是持续的交互
您可能应该让您的初始请求返回一种“任务ID”(可以是任何唯一的ID),并快速返回。同时,您在后台启动任务。然后,客户端可以轮询该特定任务的状态。您可以使用“长轮询”,其中每个请求都会一直挂起,直到状态发生变化,或者让客户端定期调用服务器。无论哪种方式,响应都只是进度(处理的记录数和当前记录的名称)。恐怕您正在尝试序列化具有后台工作成员变量的类的实例。由于后台工作程序不是可序列化对象,因此无法执行此操作 你能做的就是-
- 创建一个具有异步运行方法的类
- 在该类中创建一个成员变量,用于存储后台工作进程
- 在类中创建一个返回进度值的web方法
- 调用必须异步运行的方法
- 放置一个定期执行的客户端javascript。它应该查询web服务并询问进度。
- 更新页面并显示进度
我希望我已经正确地解释过了。如果您希望通过服务不时(在完成某个里程碑时)获得流程的更新,我建议您使用异步服务。使用WCF并创建一个异步服务(您可以查看以下主题:) 创建一些方法,如
public int onBlockComplete(IAsyncResult result)
{
//...
}
在你的客户那里处理这个问题。还可以实现在整个过程完成时回调的方法
通过这种方式,您可以处理block complete事件并在客户端上显示进度
当然,如果您在ASP.NET中实现客户端,您必须刷新页面才能看到更新。谢谢您的回答。我只是让客户端定期给服务器打电话,但我想问一下,在状态发生变化之前,您如何处理每个挂起的请求。我通过一个循环成功地实现了这一点,循环不断地检查值的变化,然后才允许函数返回新值。然而,它循环了数百万次,什么都不做,这看起来很可怕:(简而言之,我的问题是:当(!green_light){/*在停车线等待=什么都不做*/}drive();不循环数百万次,并且以最简单的方式,我可以做一些线程。Sleep()有,但我不想浪费宝贵的时间,例如,如果值在1.05秒后改变,我执行Thread.Sleep(1000)因此,在0、1、2进行检查,从而浪费0.95秒?@AndriusNaruševičius:实现长轮询将变得更为棘手-明显更为棘手。至少在AJAX/浏览器交互方面,有各种框架可以提供帮助(例如SignalR)-我不知道它们在web服务中的工作情况如何。您最好了解异步web服务支持(尤其是.NET 4.5)。不过,我肯定会从更简单的方法开始。你肯定想要一个睡眠而不是一个紧密的循环-如果用户必须多等一秒钟才能看到进度,这真的是一个问题吗?是的,我想没有什么问题,只是想追求完美,呵呵:)再次感谢:)
public int onBlockComplete(IAsyncResult result)
{
//...
}