Reputation: 851
I have an application, which have three threads. which access single datatable. Each thread print one row at single time. It should not repeat.but In my application all three threads are print all row from datatable.
I want that one row should print only once.
class Program
{
static void Main(string[] args)
{
ThreadStart testThread1Start = new ThreadStart(new program().testThread1);
ThreadStart testThread2Start = new ThreadStart(new Program().testThread2);
Thread[] testThread = new Thread[2];
testThread[0] = new Thread(testThread1Start);
testThread[1] = new Thread(testThread2Start);
foreach (Thread myThread in testThread)
{
myThread.Start();
}
Console.ReadLine();
}
private void testThread2()
{
DataTable dt = SQLite.ExecuteQuery("SELECT id,name,address FROM example ");
if (dt.Rows.Count != 0)
{
for (int i = 0; i < dt.Rows.Count; i++)
{
lock (dt.Rows[i])
{
var Id = dt.Rows[i]["Id"].ToString();
SQLite.ExecuteNonQuery("update example set DisplayDataStatus = 1 where id= '" + Id + "' ");
var name = dt.Rows[i]["name"].ToString();
var address = dt.Rows[i]["address"].ToString();
Console.WriteLine("ID:"+Id+"|Name:"+name+"|address:"+adress);
}
Console.ReadLine();
}
}
else
{}
}
private void testThread1()
{
DataTable dt = SQLite.ExecuteQuery("SELECT id,name,address FROM example ");
if (dt.Rows.Count != 0)
{
for (int i = 0; i < dt.Rows.Count; i++)
{
lock (dt.Rows[i])
{
var Id = dt.Rows[i]["Id"].ToString();
SQLite.ExecuteNonQuery("update example set DisplayDataStatus = 1 where id= '" + Id + "' ");
var name = dt.Rows[i]["name"].ToString();
var address = dt.Rows[i]["address"].ToString();
Console.WriteLine("ID:"+Id+"|Name:"+name+"|address:"+adress);
}
Console.ReadLine();
}
}
else
{}
}
}
Upvotes: 0
Views: 3571
Reputation: 3833
FIRST
Why are you re-executing the "SQLite.ExecuteQuery
" in every single thread? If you only want to print all the rows in the table without blocking UI, it's enough to have a single background Thread
that executes the query and then prints the rows.
Having more threads that try to read from the same database and try to write to the same Console
, can slow down your application instead of speeding it up (because the time of execution is the same but you have to sum the time required for all the context-switches between threads).
SECOND
Ok, suppose you still need 3 threads to execute other parallel operations.
Suppose the DataTable
instance is the same for all threads.
The lock on the Row
is only blocking the threads from writing that Row
at the same time. Suppose Thread
T1 is writing Row
R1. T2 is blocked on R1 and cannot write it. Then T1 finishes, unblocks R1 and blocks R2. Because R1 is now unblocked, T2 enters the lock
section of R1 and write R1. And so on. So all the threads write all the rows, but at different moments.
Suppose instead that every Thread
creates its own DataTable
, as your code does. If T1 locks on dt.Row[0]
, that's not the same object as dt.Row[0]
of T2! They're separate objects, so a lock section won't block the execution of any other thread!
THIRD
The "if (dt.Rows.Count != 0)
" statement is completely useless.
When you enter the for
loop, and there are no rows, the loop exits at the first check without consequences.
A check that makes sense before a for/foreach loop is the one against null list. So you can write:
"if (Rows != null) { for (int i = 0; i < Rows.Count; i++) { ... ... ... }
"
UPDATE
If you only have to print the rows to the Console, you can have 1000 threads, but since they all print to the same single Console, you have 999 useless threads. The situation is different if you have to perform some "expensive" operation on a row and then display it to the Console. In this case, try this:
startRow
and endRow
numbers. The method creates a DataTable only with those rows and print only those rows to the Console.This solution doesn't print the rows all in order, anyway. Is that a requirement?
Upvotes: 1