Problems with multi threaded Windows Forms Application

3 posts, 1 answers
  1. Justin Woolich
    Justin Woolich avatar
    2 posts
    Member since:
    Dec 2009

    Posted 29 Dec 2009 Link to this post

    Hi,

    I am having problems with a multi threaded windows forms application and using Open Access to inertact with the database.

    I have set up a demo app to demonstrate the problem (see code below), although the demo app does not represent a business problem it does expose the problem i am having when calling the scope from different threads.

    I have a class library with one class called Class1, with a single DateTime property TestDate that has been set up to persist the data to a database.

    i have another project with a windows forms application where i have set up 3 buttons, button1 populates the database with some data, button2 retreives the data from the database by calling the GetCount method in a single thread, button3 uses the ThreadPool to call GetCount on different threads multiple times and this is where i am having problems. I get various errors like object not set to an instance of an object or Error executing query... SqlConnection does not support parallel transactions etc. Do i need to syncronize calls (with a lock or similar) to the scope so only one thread is accessing the scope at any one time? or can i somehow allow the threads to use their own scopes independant from the other treads???

    Thanks

    ~~~~~~~~~~~~~~~~
    Class Library Code
    ~~~~~~~~~~~~~~~~

        [Telerik.OpenAccess.Persistent()]
        public class Class1
        {
            private DateTime _testDate;

            public DateTime TestDate
            {
                get
                {
                    return _testDate;
                }
                set
                {
                    _testDate = value;
                }
            }
        }

    ~~~~~~~~~~~~~~~~
    Windows Forms Application Code
    ~~~~~~~~~~~~~~~~

        public partial class Form1 : Form
        {
            private IObjectScope _scope = ObjectScopeProvider1.GetNewObjectScope();
           
            private delegate void UpdateLabel(string text);
            private UpdateLabel updateLabel;

            public Form1()
            {
                InitializeComponent();

                updateLabel = new UpdateLabel(OnUpdateLabel);
            }

            private void button1_Click(object sender, EventArgs e)
            {
                for (int count = 0; count < 10; count++)
                {
                    _scope.Transaction.Begin();
                    Class1 class1 = new Class1();
                    class1.TestDate = DateTime.Now;
                    _scope.Add(class1);
                    _scope.Transaction.Commit();
                }
            }

            private void button2_Click(object sender, EventArgs e)
            {
                GetCount(new object());
            }

            private void button3_Click(object sender, EventArgs e)
            {
                for (int count = 0; count < 100; count++)
                {
                    ThreadPool.QueueUserWorkItem(new WaitCallback(GetCount));
                }
            }

            private void GetCount(object obj)
            {
                try
                {
                    List<Class1> classList = null;

                    lock (_scope)
                    {
                        var classes = from class1 in _scope.Extent<Class1>()
                                      select class1;

                        classList = classes.ToList();
                    }

                    int count = 0;

                    foreach (Class1 class1 in classList)
                    {
                        DateTime classDate = class1.TestDate;
                        count++;
                    }

                    this.Invoke(updateLabel, new object[] { count.ToString() });
                }
                catch (Exception ex)
                {
                    MessageBox.Show(ex.Message);
                }
            }

            private void OnUpdateLabel(string text)
            {
                label1.Text = text;
            }  
        }

  2. Answer
    Thomas
    Admin
    Thomas avatar
    590 posts

    Posted 30 Dec 2009 Link to this post

    Hello Justin Woolich,

     multithreaded access to one scope is not our preferred style, but can nevertheless be used. All you need to do is to specify the <option.Multithreaded>True</option.Multithreaded> in your backend configuration. This will synchronize all access to the runtime.

    Happy new year!

    Kind regards,
    Thomas
    the Telerik team

    Instantly find answers to your questions on the new Telerik Support Portal.
    Watch a video on how to optimize your support resource searches and check out more tips on the blogs.
  3. DevCraft banner
  4. Justin Woolich
    Justin Woolich avatar
    2 posts
    Member since:
    Dec 2009

    Posted 30 Dec 2009 Link to this post

    Hi Thomas,

    Thanks for you answer, i also found this article which uses thread slots which may be even better for my application.

    http://www.telerik.com/support/kb/orm/general/best-practices-in-winforms-with-orm.aspx

    Cheers

    -Justin.
Back to Top