CodeGuru Home VC++ / MFC / C++ .NET / C# Visual Basic VB Forums Developer.com
Results 1 to 1 of 1

Threaded View

  1. #1
    Join Date
    Sep 2010
    Posts
    3

    Unhappy Deadlock Task Factory Treading Problem

    Hi all C# gurus I need advice on Deadlock

    Using .NET4.0 / VS 2010

    I have a code structure for Window Service, multithreading, task factory like

    public partial class rs : ServiceBase
    {
    private Queue jobQueue = Queue.Synchronized(new Queue());
    private Queue DatafeedQueue = Queue.Synchronized(new Queue());
    private Dictionary<...> ScheduleJobs = new Dictionary<...>();
    private AutoResetEvent _BlockThreadTaskScheduler = new AutoResetEvent(true);
    private AutoResetEvent _BlockThreadDatafeedSourceTaskScheduler = new AutoResetEvent(false);
    private LimitedConcurrencyLevelTaskScheduler _TaskScheduler;
    private LimitedConcurrencyLevelTaskScheduler _DatafeedSourceTaskScheduler;

    public rs()
    {
    InitializeComponent();
    _timer = new System.Timers.Timer(POLL_INTERVAL_MINUTE * 60 * 1000);
    _timer.Elapsed += new System.Timers.ElapsedEventHandler(_timer_Elapsed);
    _TaskScheduler = new LimitedConcurrencyLevelTaskScheduler(2);
    _DatafeedSourceTaskScheduler = new LimitedConcurrencyLevelTaskScheduler(1);

    protected void _timer_Elapsed(object sender, ElapsedEventArgs e)
    {
    try
    {
    DatafeedQueue.Clear();
    try
    {
    (Execute a stored procedure here)
    while(xxx.Read())
    {
    DatafeedObj dfo = new DatafeedObj();
    ...
    DatafeedQueue.Enqueue(dfo);
    }
    }
    catch()...

    TaskFactory DatafeedSourceFactory = new TaskFactory(_DatafeedSourceTaskScheduler);
    // DatafeedQueue.Count = 3
    for (int i = 0; i < DatafeedQueue.Count; i++)
    {
    DatafeedSourceFactory.StartNew(() => processDatafeedQueue());
    }

    _BlockThreadDatafeedSourceTaskScheduler.Set();

    }
    catch()...
    }
    private void processDatafeedQueue()
    {
    _BlockThreadDatafeedSourceTaskScheduler.WaitOne();
    try
    {
    lock (DatafeedQueue.SyncRoot)
    {
    if (DatafeedQueue.Count > 0)
    {
    DatafeedObj dfo = ((DatafeedObj)(DatafeedQueue.Dequeue()));

    #region DataFeed Type A

    ScheduleJobs = (Calls a static class, static method);
    jobQueue = (Calls a static class, static method turn ScheduleJobs dictionary into Queue);
    var factory = new TaskFactory(_TaskScheduler);
    for (int i = 0; i < jobQueue.Count; i++)
    {
    factory.StartNew(() => startTypeA());
    }

    #endregion

    #region DataFeed Type B

    ScheduleJobs = (Calls a static class, static method);
    jobQueue = (Calls a static class, static method turn ScheduleJobs dictionary into Queue);
    var factory = new TaskFactory(_TaskScheduler);
    for (int i = 0; i < jobQueue.Count; i++)
    {
    factory.StartNew(() => startTypeB());
    }

    #endregion

    #region DataFeed Type C

    ScheduleJobs = (Calls a static class, static method);
    jobQueue = (Calls a static class, static method turn ScheduleJobs dictionary into Queue);
    var factory = new TaskFactory(_TaskScheduler);
    for (int i = 0; i < jobQueue.Count; i++)
    {
    factory.StartNew(() => startTypeC());
    }

    #endregion
    }
    }
    }
    if (_TaskScheduler.NumberOfRemainingScheduledTasks == 0)
    {
    _BlockThreadDatafeedSourceTaskScheduler.Set();
    }
    }
    void startTypeA()
    {
    (In this method, it creates a object from another project class which calls a WCF Service and select data and insert into local db and run stored procedures)
    }
    void startTypeB()
    {
    (Same as startTypeA but calls a different WCF and insert into the same set of tables which startTypeA also insert into then also run a same set of stored procedures)
    }
    void startTypeC()
    {
    (Same as startTypeC but calls a different WCF and into different set of tables than startTypeA and startTypeB then run different set of stored procedures)
    }

    ...

    I was able to grab all the data from all 3 set of WCF services but the problem is after Type A and Type B insert the data and both calls the same set of stored procedures a few Job Queue had Error 1205, deadlock. Then after service has stopped, I had to manually rerun the stored procedures to process those leftover.

    Can anyone know how to fix the deadlock, also I use AutoResetEvent to keep a thread blocked while another thread is processing. It doesn't seem like its doing its job.

    I was thinking for alternative way but I would like to keep the same logic, task factory...

    My alternative way, non-tested with actual code, but I wrote a draft similar to what I needed, but I am unsure if deadlock will still exists

    class Program
    {
    static SemaphoreSlim _sem = new SemaphoreSlim(3);

    static void Main()
    {
    for (int i = 1; i <= 3; i++)
    {
    new Thread(RunThisMethod).Start(i);
    }
    Console.ReadLine();
    }

    static void RunThisMethod(Object id)
    {
    Console.WriteLine(id + " wants to enter");
    _sem.Wait();
    if (id.ToString() == "1")
    {
    Console.WriteLine("Start Type A");
    Thread.Sleep(3000);
    Console.WriteLine("End Type A");
    }
    else if (id.ToString() == "2")
    {
    Console.WriteLine("Start Type B");
    Thread.Sleep(6000);
    Console.WriteLine("End Type B");
    }
    else if (id.ToString() == "3")
    {
    Console.WriteLine("Start Type C");
    Thread.Sleep(9000);
    Console.WriteLine("End Type C");
    }
    _sem.Release();
    }
    }
    Last edited by d87c; August 22nd, 2012 at 06:46 PM.

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  





Click Here to Expand Forum to Full Width

Featured