【问题标题】:Unexpected result when calling the same web service multiple times simultaneously同时多次调用同一个 Web 服务时出现意外结果
【发布时间】:2010-12-10 19:45:18
【问题描述】:

同时(即在多个线程中)向同一个 Web 服务操作发出多个请求时遇到问题。

每次调用 Web 服务时,我都会将其记录到控制台,所以我的输出类似于

Calling OperationA with paramA = 'A'
Calling OperationA with paramA = 'B'
Calling OperationA with paramA = 'C'
Calling OperationA with paramA = 'D'
...
Calling OperationA with paramA = 'Z'

这表明我正在使用不同的参数调用相同的操作。

我正在使用 Fiddler 来跟踪这些请求,并且我希望按照它们在应用程序上发出的顺序查看我的所有请求。但是全错了:请求都是乱序的,有的请求不止一次发出,有的根本没有发出(就是我的printf说我调用了,但是Fiddler什么也没显示)。

问题似乎是在短时间内发出大量请求,因为如果我在每次调用之间添加一个Thread.Sleep(2000),一切都会像魅力一样工作。

这是某种预期的行为吗?为什么请求没有正确排队?

顺便说一下,这是一个 C# 2.0 客户端,使用 wsdl.exe 生成的代理类调用 AXIS 2.0 安全 Web 服务,我使用的是异步“beginOperation”和代理类中的“endOperation”方法来发出请求。

编辑:这是我一遍又一遍地调用此操作的方式:


foreach(List listOfMyClass1 in  listOfListOfMyClass1)
{
 MyClass2[] webServiceParameter = listOfMyClass1.ToArray();

 // Here I log that I'm calling the operation, and print every element in webServiceParameter

 IAsyncResult ar = wsClient.BeginOperationA(webServiceParameter);

 listOfAsyncResults.Add(ar);

  // System.Threading.Thread.Sleep(2000); --> This solves the problem..
}

foreach(IAsyncResult ar in listOfAsyncResults)
{
 WebServiceResultClass result = wsClient.EndOperationA(ar);
}

【问题讨论】:

  • 嗯。您是否在任何给定时间只看到两个同时请求?会不会是每个远程服务器的 2 个连接的 http 限制搞砸了?
  • 我不知道有这样的限制......这是怎么回事?但看起来有时有很多(超过 2 个)请求被处理(通过查看 Fiddler)。

标签: c# web-services .net-2.0


【解决方案1】:

我不希望它们以任何特定的顺序出现,但每个应该只出现一次。

我将使用通灵调试来尝试找出问题所在...我怀疑你有这样的循环:

foreach (string input in data)
{
    new Thread(() => CallWebService(input)).Start();
}

这是捕获循环变量 - 这是一个bad idea。不过很容易解决:

foreach (string input in data)
{
    string copy = input;
    new Thread(() => CallWebService(copy)).Start();
}

(上一个链接将解释发生了什么......和here's the second part。)

如果 不是,请给我们一些代码 - 否则我们只是在猜测。

【讨论】:

  • 我测试了它,这似乎不是问题。我编辑了我的问题并放入了我的代码的简化版本。
  • 您为什么不希望它们按任何特定顺序排列?系统的哪个部分对此进行控制?我曾想象过,当调用 beginOperation 方法时,.NET 会启动一个新线程(“立即”)并立即分派这个请求,导致请求以与循环变量迭代相同的顺序发出。跨度>
  • @dsetton:每个主机都有连接限制。我希望当连接都在进行中,并且有多个线程排队请求时,处理这些请求的顺序可能无法确定。我当然不想依赖它。
  • @dsetton:好的,你的样本看起来没问题。你有没有机会把它放到一个简短但完整的程序中来演示这个问题?
  • 好的.. 但是如何?我的意思是,我还应该放什么?问题是如果listOfListOfMyClass1 有很多元素,这个循环会非常快地发出很多请求,然后我就会看到我描述的所有混乱。我可以将带有请求的 Fiddler 会话放在这里.. 然后你就可以将它与 printf 输出进行比较.. 这有帮助吗?
【解决方案2】:

好的,所以问题是在每次迭代时更改在循环外声明的变量并在循环内使用它的老问题。我的意思是,它有点类似于这个:

MyClass c = new MyClass();
IList<MyClass> myClassList = new List<MyClass>();
for(int i = 0; i < someInt; i++)
{
    c.SomeProperty = i;
    myClassList.Add(c);
}
// And here every "SomeProperty" is the same for every element in the list, since every element references the same variable.

更具体地说,webServiceParameter 数组(参见问题中的代码)实际上被分配给另一个变量(在循环外声明)的属性,并且该变量被传递给服务调用。

因此,当快速调用过多时,当这些调用被分派时,数组将包含上次迭代的值,从而导致“重复请求”。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-08-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多