We're looking to avoid unresponsiveness on our UI for a potentially intensive database call. I've been experimenting with different ways to reach the following scenario.
- User i开发者_JAVA百科nvokes the functionality.
- A thread is forked that executes the functionality.
- The user has the option of canceling the functionality.
- a. If the user does not cancel, the thread works with independent data and spawns some other, unrelated UI.
- b. If the user does cancel, cancel the thread's processing and cancel any related activity (such as the SQL stored procedure we'll be calling -- irrelevant for the purposes of this question).
Being a low-level, C++ kinda guy myself, I first tried a straight Thread solution. Then, I tried looking into .NET's BackgroundWorker solution (C#).
Here's the code that I use to simulate that potentially-intensive operation that the thread is to handle.
/// <summary>
/// Simulates the processing for a query that is pretty much
/// unresponsive after it's been invoked.
/// </summary>
public void SimulateSuperLongQuery ()
{
// Pass the time, for a very long time...
for (int i=0; i < int.MaxValue; i++)
SimulateSuperLongQuery();
_completed = true;
}
Peculiarly...
- My plain Thread solution works fine when calling that method.
- The BackgroundWorker solution throws a StackOverflowException when calling that method!
Does anyone have any idea why the BackgroundWorker causes an exception?
Code, in case it helps. Here's a bit of the BackgroundWorker code. It's straight off of the MSDN website.
BackgroundWorker bw = new BackgroundWorker();
bw.WorkerSupportsCancellation = true;
bw.DoWork += new DoWorkEventHandler(bw_DoWork);
if (bw.IsBusy != true)
{
bw.RunWorkerAsync();
}
// ...
private void bw_DoWork (object sender, DoWorkEventArgs e)
{
QuerySimulator query = new QuerySimulator();
query.SimulateSuperLongQuery();
}
Here's a bit of my plain vanilla code.
// Fire up a thread to run a query
QuerySimulator query = new QuerySimulator();
Thread queryThread = new Thread(query.SimulateSuperLongQuery);
As people have already spotted, it is clear that you will run into a Stackoverflow, thread or not - just that in the single-threaded case I suspect that the CLR was able to do tail-call optimization.
If you want to simulate blocking thread, do just that: block it.
Thread.Sleep(TimeSpan.FromSeconds(5));
Without seeing all the code it's kind of hard to tell for sure, but I'm almost certain your SimulateSuperLongQuery code will cause a StackOverflowException no matter what. It's calling itself recursively forever (or trying to, anyway).
How long does your plain Thread solution take to run? If you're not seeing an exception in that version, it may just be getting swallowed somewhere.
精彩评论