开发者

Object changed by another thread

This problem is en开发者_开发技巧countered in part of a complicated system where many threads need to access to the same method. This project is written in C#. To simplify the problem, I use the following illustration:

I have two customised classes, the parent class of these two classes is the same. The two classes are Apple and Orange, the parent is Fruit. The problem came when I expect an apple, but it is actually an Orange. This happens sometimes, not not a rare event, probably 10% of the time.

public void MethodAlpha(object food)
{
   lock(this)
   {
       FoodObj foodObj = Converter.XMLStringToObject(food, ...) //"food" is a string

       if(foodObj.FoodType == StringConstants.Apple)
       {
           Apple apple = (Apple)foodObj.FoodObject; <--InvaildCastException
           ...
       }
       ...
   }
}

The InvaildCastException says I am trying to cast an Orange to an Apple, when I have already handled it by "lock(this)" and the if checking. Have I handled it incorrectly? How should I resolve this issue?


you say food is a string; now, strings are immutable, so that hasn't changed during the method - and the parameter food is not by-ref (ref), so that hasn't changed during the method.

Converter.XMLStringToObject appears (hard to say) to parse the string to an object, so there is no shared state there unless you have some cache that you haven't told us about.

So... this is just a parsing bug in your code; nothing to do with threading.

Note: method parameters and variables are per call - they are isolated (unless they refer to shared state).

This is not a threading issue. Just a run-of-the-mill bug. At some point during parsing, you've called it an apple, but assigned it an orange. Trace through XMLStringToObject to find it, looking in particular at where .FoodType and FoodObject get assigned.

As an aside - lock(this) is a bad idea in general; in this case, it also does nothing useful since you have no shared state to protect. If there was a use, having a dedicated object for this would be preferred:

private readonly object syncLock = new object();
...
lock(syncLock) {...}


As Marc Gravell suggested use a separate Object instance for lock purpose and to get rid of the exception

Apple apple = foodObj.FoodObject as Apple;

if(apple != null)
{
 // do something here
}
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜