我需要一个控制台应用程序,它将调用 WebMethod。
它必须是异步的,并且没有超时(我们不知道这个方法处理任务需要多长时间)。
这是一个好的方式吗?
它必须是异步的,并且没有超时(我们不知道这个方法处理任务需要多长时间)。
这是一个好的方式吗?
[WebMethod]
[SoapDocumentMethod(OneWay = true)]
??
[WebMethod]
[SoapDocumentMethod(OneWay = true)]
??
如果需要结果,请勿使用单向调用
首先,如果您需要从方法中获得响应,则不要使用[SoapDocumentMethod(OneWay = true)]
。此属性创建了一个“发出请求并忘记”的调用,它不会将响应返回给调用方,必须返回void
。相反,使用常规方法调用并异步调用它。
一个方法还是两个方法?
如果您正在使用 ASMX,则有两种基本解决方案:一个具有非常长的超时时间的方法,或者两个方法(如 @Aaronaught suggested above):一个用于启动操作并返回操作的 ID,另一个用于传递 ID 并检索结果(如果可用)。
个人而言,在大多数情况下,我不建议使用这种两个方法的方法,因为其中涉及的额外复杂性包括:
ThreadPool.QueueUserWorkItem
启动的后台任务时,像Request
和Response
这样的ASP.NET内置对象是不可用的。确实,在某些情况下,两种方法的方法可能更好地扩展,并且对于客户端和服务器之间的网络连接断开更具有韧性。如果您需要几个小时后再获取结果,则应考虑此选项。但是,如果您的操作只需要几分钟,并且可以保证客户端保持连接,则考虑到两种方法的额外开发复杂性,我认为这是最后的选择,仅在单方法解决方案无法满足您的需求时使用。
无论如何,解决方案需要两个部分。首先,您需要从客户端异步调用该方法。其次,您需要延长客户端和服务器上的超时时间。我在下面介绍这两个部分。 异步调用 ASMX Web 服务 要从命令行应用程序异步调用 ASMX Web 服务,请参阅本文第2页开始的内容。它展示了如何使用较新的基于事件的异步模式从 .NET 客户端应用程序异步调用 Web 服务。请注意,旧的 .NET 1.0 方法在此处所描述的依赖于代理上的 BeginXXX/EndXXX 方法不再建议使用,因为 Visual Studio 的代理生成器不会创建这些方法。最好使用以上链接中提供的基于事件的模式。void KickOffAsyncWebServiceCall(object sender, EventArgs e)
{
HelloService service = new HelloService();
//Hookup async event handler
service.HelloWorldCompleted += new
HelloWorldCompletedEventHandler(this.HelloWorldCompleted);
service.HelloWorldAsync();
}
void HelloWorldCompleted(object sender,
HelloWorldCompletedEventArgs args)
{
//Display the return value
Console.WriteLine (args.Result);
}
延长服务器和客户端超时时间
为了防止超时,http://www.dotnetmonster.com/Uwe/Forum.aspx/asp-net-web-services/5202/Web-Method-TimeOut 提供了一个很好的总结,介绍如何调整客户端和服务器端的超时时间。您在问题中没有说明您是否拥有服务器端方法或只是客户端调用,因此以下摘录涵盖了这两种情况:
有两个设置会影响 WebService 调用超时行为:public enum JobStatus { Running, Completed, Failed };
public class MyService : WebService
{
[WebMethod]
public int BeginJob()
{
int id = GetJobID();
// Save to a database or persistent data source
SaveJobStatus(id, JobStatus.Running);
ThreadPool.QueueUserWorkItem(s =>
{
// Do the work here
SaveJobStatus(id, JobStatus.Completed);
}
return id;
}
[WebMethod]
public JobStatus GetJobStatus(int id)
{
// Load the status from database or other persistent data source
return ( ... )
}
}
IsOneWay = true
。