Synchronization problem

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • Johan Öhrn

    Synchronization problem

    Hi,

    I'm working with an asp.net 2.0 application.

    The application I'm working with come with it's own assemblies which calls
    out to code in my assembly.
    It may call out to my code during a request, i.e. I click on a link in the
    application or when the application does some background processing in a
    different thread.

    My problem is when my code gets called from a background thread. The thread
    itself is created in the following manner:
    ThreadPool.Queu eUserWorkItem(n ew WaitCallback(th is.WorkThread)) ;
    Note that this code is out of my control.

    This thread (hereby refered to as job) call one of my functions to get a
    collection of items which the job operates upon. The same job may call my
    function any number of times during it's execution. The problem I have is
    that the application (ouf of my control) throws an exception if my function
    returns different data between from one call to the next. So I must somehow
    make sure that I always return the same data to the job.

    Sometimes as I mentioned my code is executed in the context of the current
    request. I must still make sure that my function return the same data during
    the whole request. In this scenario I can store a cached version of the data
    in the HttpContext.Ite ms collection the first time it's asked for and then
    return that cached data for any subsequent call to my function.

    So my problem is that I can't find a working solution for the scenario where
    my function is called from a background thread because I don't have access
    to the HttpContext. I've tried to store data in the Thread Local Store (TLS)
    but it turns out that the TLS is not cleared when the threads are reused by
    the ThreadPool.

    If anyone have an idea how I can fix this issue I'd be really glad!


    I'm attaching some pseudo code that illustrates the problem:
    (Look here for a cleaner version of the code:
    http://rafb.net/p/oKxBWB39.html)

    namespace Product.Proprie tary.Assembly.O utOfMyControl

    {

    public class SomeWorkToBeDon e

    {

    public void DoWork()

    {

    ThreadPool.Queu eUserWorkItem(n ew WaitCallback(th is.WorkThread)) ;

    }



    private void WorkThread(obje ct obj)

    {

    MyOwn.Assembly. SomeHelperClass helper = new
    MyOwn.Assembly. SomeHelperClass ();



    ArrayList items = helper.GetItems ();



    int unknownNumberOf TimesToGetItems = new Random().Next() ;

    for (int i = 0; i < unknownNumberOf TimesToGetItems ; i++)

    {

    if (helper.GetItem s().Count != items.Count)

    throw new Exception("You didn't return the same items as
    the last call. I throw an exception!");

    }

    }

    }

    }



    namespace MyOwn.Assembly

    {

    public class SomeHelperClass

    {

    public ArrayList GetItems()

    {

    // I need to make sure I return the same items for the rest of
    this context!

    // If i'm not called from a background thread I have access to
    the HttpContext object in which I can cache the items and they are magically
    removed when the request ends.

    if (HttpContext.Cu rrent != null)

    {

    ArrayList entries = HttpContext.Cur rent.Items[GetHashCode()]
    as ArrayList;

    if (entries == null)

    {

    HttpContext.Cur rent.Items[GetHashCode()] = entries = new
    ArrayList(BackE ndStore.GetItem s());

    }

    return entries;

    }

    else

    {

    // No HttpContext because I was called from a background
    thread (a job) - Bummer! What do I do now???

    // I know! Pray that the backend store will return the same
    items each time for the rest of this job, i.e. rest of the execution of the
    thread before it's reused.

    return BackEndStore.Ge tItems();

    }

    }

    }





    public class BackEndStore

    {

    public static ArrayList GetItems()

    {

    // I'm not in control of when items are changed in the backend
    store!

    ArrayList list = new ArrayList();

    int unknownNumberOf Items = new Random().Next() ;

    for (int i = 0; i < unknownNumberOf Items; i++)

    list.Add(1);

    return list;

    }

    }

    }


  • =?Utf-8?B?YnJ1Y2UgYmFya2Vy?=

    #2
    RE: Synchronization problem

    unfortunately, .net failed to provide a factory model for the thread pool,
    and there are no hooks/events on dequeueing an thread.

    your 3rd party app seems to have a design flaw. they should pass some
    content information when they make the callback. you should contact them.


    -- bruce (sqlwork.com)


    "Johan Öhrn" wrote:
    Hi,
    >
    I'm working with an asp.net 2.0 application.
    >
    The application I'm working with come with it's own assemblies which calls
    out to code in my assembly.
    It may call out to my code during a request, i.e. I click on a link in the
    application or when the application does some background processing in a
    different thread.
    >
    My problem is when my code gets called from a background thread. The thread
    itself is created in the following manner:
    ThreadPool.Queu eUserWorkItem(n ew WaitCallback(th is.WorkThread)) ;
    Note that this code is out of my control.
    >
    This thread (hereby refered to as job) call one of my functions to get a
    collection of items which the job operates upon. The same job may call my
    function any number of times during it's execution. The problem I have is
    that the application (ouf of my control) throws an exception if my function
    returns different data between from one call to the next. So I must somehow
    make sure that I always return the same data to the job.
    >
    Sometimes as I mentioned my code is executed in the context of the current
    request. I must still make sure that my function return the same data during
    the whole request. In this scenario I can store a cached version of the data
    in the HttpContext.Ite ms collection the first time it's asked for and then
    return that cached data for any subsequent call to my function.
    >
    So my problem is that I can't find a working solution for the scenario where
    my function is called from a background thread because I don't have access
    to the HttpContext. I've tried to store data in the Thread Local Store (TLS)
    but it turns out that the TLS is not cleared when the threads are reused by
    the ThreadPool.
    >
    If anyone have an idea how I can fix this issue I'd be really glad!
    >
    >
    I'm attaching some pseudo code that illustrates the problem:
    (Look here for a cleaner version of the code:
    http://rafb.net/p/oKxBWB39.html)
    >
    namespace Product.Proprie tary.Assembly.O utOfMyControl
    >
    {
    >
    public class SomeWorkToBeDon e
    >
    {
    >
    public void DoWork()
    >
    {
    >
    ThreadPool.Queu eUserWorkItem(n ew WaitCallback(th is.WorkThread)) ;
    >
    }
    >
    >
    >
    private void WorkThread(obje ct obj)
    >
    {
    >
    MyOwn.Assembly. SomeHelperClass helper = new
    MyOwn.Assembly. SomeHelperClass ();
    >
    >
    >
    ArrayList items = helper.GetItems ();
    >
    >
    >
    int unknownNumberOf TimesToGetItems = new Random().Next() ;
    >
    for (int i = 0; i < unknownNumberOf TimesToGetItems ; i++)
    >
    {
    >
    if (helper.GetItem s().Count != items.Count)
    >
    throw new Exception("You didn't return the same items as
    the last call. I throw an exception!");
    >
    }
    >
    }
    >
    }
    >
    }
    >
    >
    >
    namespace MyOwn.Assembly
    >
    {
    >
    public class SomeHelperClass
    >
    {
    >
    public ArrayList GetItems()
    >
    {
    >
    // I need to make sure I return the same items for the rest of
    this context!
    >
    // If i'm not called from a background thread I have access to
    the HttpContext object in which I can cache the items and they are magically
    removed when the request ends.
    >
    if (HttpContext.Cu rrent != null)
    >
    {
    >
    ArrayList entries = HttpContext.Cur rent.Items[GetHashCode()]
    as ArrayList;
    >
    if (entries == null)
    >
    {
    >
    HttpContext.Cur rent.Items[GetHashCode()] = entries = new
    ArrayList(BackE ndStore.GetItem s());
    >
    }
    >
    return entries;
    >
    }
    >
    else
    >
    {
    >
    // No HttpContext because I was called from a background
    thread (a job) - Bummer! What do I do now???
    >
    // I know! Pray that the backend store will return the same
    items each time for the rest of this job, i.e. rest of the execution of the
    thread before it's reused.
    >
    return BackEndStore.Ge tItems();
    >
    }
    >
    }
    >
    }
    >
    >
    >
    >
    >
    public class BackEndStore
    >
    {
    >
    public static ArrayList GetItems()
    >
    {
    >
    // I'm not in control of when items are changed in the backend
    store!
    >
    ArrayList list = new ArrayList();
    >
    int unknownNumberOf Items = new Random().Next() ;
    >
    for (int i = 0; i < unknownNumberOf Items; i++)
    >
    list.Add(1);
    >
    return list;
    >
    }
    >
    }
    >
    }
    >
    >
    >

    Comment

    • Johan Öhrn

      #3
      Re: Synchronization problem

      Hi,

      Thanks for the bad news :)

      / Johan

      "bruce barker" <brucebarker@di scussions.micro soft.comwrote in message
      news:E4E80BF6-0F44-4DBD-BEDF-CB22DF4A5896@mi crosoft.com...
      unfortunately, .net failed to provide a factory model for the thread pool,
      and there are no hooks/events on dequeueing an thread.
      >
      your 3rd party app seems to have a design flaw. they should pass some
      content information when they make the callback. you should contact them.
      >
      >
      -- bruce (sqlwork.com)
      >
      >
      "Johan Öhrn" wrote:
      >
      >Hi,
      >>
      >I'm working with an asp.net 2.0 application.
      >>
      >The application I'm working with come with it's own assemblies which
      >calls
      >out to code in my assembly.
      >It may call out to my code during a request, i.e. I click on a link in
      >the
      >application or when the application does some background processing in a
      >different thread.
      >>
      >My problem is when my code gets called from a background thread. The
      >thread
      >itself is created in the following manner:
      >ThreadPool.Que ueUserWorkItem( new WaitCallback(th is.WorkThread)) ;
      >Note that this code is out of my control.
      >>
      >This thread (hereby refered to as job) call one of my functions to get a
      >collection of items which the job operates upon. The same job may call my
      >function any number of times during it's execution. The problem I have is
      >that the application (ouf of my control) throws an exception if my
      >function
      >returns different data between from one call to the next. So I must
      >somehow
      >make sure that I always return the same data to the job.
      >>
      >Sometimes as I mentioned my code is executed in the context of the
      >current
      >request. I must still make sure that my function return the same data
      >during
      >the whole request. In this scenario I can store a cached version of the
      >data
      >in the HttpContext.Ite ms collection the first time it's asked for and
      >then
      >return that cached data for any subsequent call to my function.
      >>
      >So my problem is that I can't find a working solution for the scenario
      >where
      >my function is called from a background thread because I don't have
      >access
      >to the HttpContext. I've tried to store data in the Thread Local Store
      >(TLS)
      >but it turns out that the TLS is not cleared when the threads are reused
      >by
      >the ThreadPool.
      >>
      >If anyone have an idea how I can fix this issue I'd be really glad!
      >>
      >>
      >I'm attaching some pseudo code that illustrates the problem:
      >(Look here for a cleaner version of the code:
      >http://rafb.net/p/oKxBWB39.html)
      >>
      >namespace Product.Proprie tary.Assembly.O utOfMyControl
      >>
      >{
      >>
      > public class SomeWorkToBeDon e
      >>
      > {
      >>
      > public void DoWork()
      >>
      > {
      >>
      > ThreadPool.Queu eUserWorkItem(n ew
      >WaitCallback(t his.WorkThread) );
      >>
      > }
      >>
      >>
      >>
      > private void WorkThread(obje ct obj)
      >>
      > {
      >>
      > MyOwn.Assembly. SomeHelperClass helper = new
      >MyOwn.Assembly .SomeHelperClas s();
      >>
      >>
      >>
      > ArrayList items = helper.GetItems ();
      >>
      >>
      >>
      > int unknownNumberOf TimesToGetItems = new Random().Next() ;
      >>
      > for (int i = 0; i < unknownNumberOf TimesToGetItems ; i++)
      >>
      > {
      >>
      > if (helper.GetItem s().Count != items.Count)
      >>
      > throw new Exception("You didn't return the same items
      >as
      >the last call. I throw an exception!");
      >>
      > }
      >>
      > }
      >>
      > }
      >>
      >}
      >>
      >>
      >>
      >namespace MyOwn.Assembly
      >>
      >{
      >>
      > public class SomeHelperClass
      >>
      > {
      >>
      > public ArrayList GetItems()
      >>
      > {
      >>
      > // I need to make sure I return the same items for the rest
      >of
      >this context!
      >>
      > // If i'm not called from a background thread I have access
      >to
      >the HttpContext object in which I can cache the items and they are
      >magically
      >removed when the request ends.
      >>
      > if (HttpContext.Cu rrent != null)
      >>
      > {
      >>
      > ArrayList entries =
      >HttpContext.Cu rrent.Items[GetHashCode()]
      >as ArrayList;
      >>
      > if (entries == null)
      >>
      > {
      >>
      > HttpContext.Cur rent.Items[GetHashCode()] = entries =
      >new
      >ArrayList(Back EndStore.GetIte ms());
      >>
      > }
      >>
      > return entries;
      >>
      > }
      >>
      > else
      >>
      > {
      >>
      > // No HttpContext because I was called from a background
      >thread (a job) - Bummer! What do I do now???
      >>
      > // I know! Pray that the backend store will return the
      >same
      >items each time for the rest of this job, i.e. rest of the execution of
      >the
      >thread before it's reused.
      >>
      > return BackEndStore.Ge tItems();
      >>
      > }
      >>
      > }
      >>
      > }
      >>
      >>
      >>
      >>
      >>
      > public class BackEndStore
      >>
      > {
      >>
      > public static ArrayList GetItems()
      >>
      > {
      >>
      > // I'm not in control of when items are changed in the
      >backend
      >store!
      >>
      > ArrayList list = new ArrayList();
      >>
      > int unknownNumberOf Items = new Random().Next() ;
      >>
      > for (int i = 0; i < unknownNumberOf Items; i++)
      >>
      > list.Add(1);
      >>
      > return list;
      >>
      > }
      >>
      > }
      >>
      >}
      >>
      >>
      >>

      Comment

      Working...