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;
}
}