Tian Min Huang said:
Hello David,
Thanks for your post. I reviewed your description carefully, and now I'd
like to share the following information with you:
Does the problem still occur if you put Sleep(500) in the worker thread? If
so, I am afraid that you may use some synchronization objects say, mutext,
etc, which may synchronize the UI and worker threads.
I've tried 'Sleep' with different parameters, including, as you can see
below, '0'. The documentation explicitly states that Sleep(0) yields control
to other threads. I suspect that what is happening is that the worker thread
is indeed being given lowest priority but since it is always 'ready-to-run'
the Windows dispatcher appears not to dispatch UI repaint events (as long as
there is a thread in the process ready to run).
The file being searched is very large, often in the GB range. The worker
thread is scanning 1MB chunks. While it is possible to add 'Sleep(500)' once
in the beginning, it is not viable on every iteration. In a 1GB file, there
will be 1000 iterations.
The symptoms: once the worker thread starts, screen updates stop. When the
thread finishes, the screen repaints. In normal operation the user kicks
off a search of the file and continues to work with the rest of the UI.
While the search is going, the UI uses a timer to refer to the status of the
search and updates status field on the screen. What I see is only the final
status (the thread is done) then the screen comes back.
My objectives: to have the worker thread not interfere with the UI event
dispatch mechanism (repaint in particular). I was hoping that by setting the
worker thread's priority to the lowest it would soak up 'unused' cycles
only.
Lastly, I can't imagine how a mutex would help in this situation. The last
resort is switching from a search thread to a different process which is
much more awkward.
In addition, I agree with Miha that you can provide a simple reproducible
sample/code snippet which will be most helpful for us to pinpoint the
problem and resolution.
The thread starting code:
public void StartSearch()
{
Thread thread = new Thread(new ThreadStart(runSearch));
thread.Name = "logFileSearcher";
//-- make sure thread does not constipate normal threads
thread.Priority = ThreadPriority.Lowest;
//-- kick off the thread
thread.Start();
}
The worker thread (asynchronous portion)
private void runSearch()
{
//-- open our copy of file handle to file
//-- try to open the file (shared with creator)
fs = File.Open(fileName, FileMode.Open,
FileAccess.Read, FileShare.ReadWrite);
//-- position to start of search spot
currentOffset = fs.Seek(startOffset, SeekOrigin.Begin);
//-- 1MB read into memory
loadChunk();
//-- leading byte
byte leadByte = (byte)searchString[0];
//-- yield to other threads including UI
Thread.Sleep(0);
while (!abortSearch)
{
try
{
while (true)
{
advance:
if (buffer[buffOffset++] != leadByte)
continue;
//-- compare the rest of the string
int j = 0;
for (int i = 1; i < searchString.Length; j++, i++)
{
if (buffer[buffOffset + j] == (byte)searchString
)
continue;
//-- we have a mis-match
goto advance;
}
//-- we have a match
lock (this)
{
matchesFound.Add(startOffset + buffOffset);
//-- yield to other threads
Thread.Sleep(0);
}
//-- skip over matched string
buffOffset += searchString.Length;
}
}
catch
{
//-- ran off end of buffer... load next 1MB chunkr
currentOffset += buffOffset;
loadChunk();
//-- check for end of file
if (buffer.Length == 0)
break;
//-- yield to other threads
Thread.Sleep(0);
}
}
if (abortSearch)
searchStatus = eStatus.Aborted;
else
searchStatus = eStatus.Done;
}
}
I look forward to hearing from you.
Thanks for your prompt help
-David