.NET Forum / Languages / C# / November 2007
Asynchronous Process Question
|
|
Thread rating:  |
Susan - 02 Aug 2006 18:34 GMT I have a process that takes a while to run so I have it running asynchronously so that the user can continue working. My question is that I want to killl the process if the user changes the search parameters before the callback method is called. Any ideas of how to do this or if it even matters? I did not know if calling the asynch process a new time kills the previous one or not.
Thank you for your help. Susan
John Duval - 02 Aug 2006 19:16 GMT > I have a process that takes a while to run so I have it running > asynchronously so that the user can continue working. My question is that I [quoted text clipped - 5 lines] > Thank you for your help. > Susan Hi Susan, Can you post some code? It seems like you can just kill the process using the object reference that you have:
static void Main(string[] args) { Process p = new Process(); p.StartInfo.FileName = @"C:\WINDOWS\system32\notepad.exe"; p.Start();
Console.WriteLine("press enter to kill process"); Console.ReadLine(); p.Kill(); return; }
Hope this helps, John
Susan - 02 Aug 2006 20:19 GMT I do not think that will work. Here's code snippets: private CountDelegate dDeleg;
private void GetResults () { /*get the actual results from database, but in limited number (25 per page) to increase response time*/
if (_newQuery) { cDeleg = new CountDelegate(Count); AsyncCallback cb = new AsyncCallback (CountCallback); cDeleg.BeginInvoke (tgts, cb, "countDelegate"); } }
private void CountCallback (IAsyncResult ar) { cDeleg.EndInvoke (ar); SetCount(); //just something letting the user know how many results there are }
I didn't know if there was a way to force the end invoke even though the process is not completed. I know that there is not cancel even, but am hoping there is a way to similate one... Any ideas?
Thank you, Susan
> > I have a process that takes a while to run so I have it running > > asynchronously so that the user can continue working. My question is that I [quoted text clipped - 24 lines] > Hope this helps, > John Pieter Breed - 02 Aug 2006 21:42 GMT Hi Susan,
(sorry about the bad spelling... its late, and I am not a native english speaker ;) )
Fact of the matter is this: You are now doing multithreaded programming. The best way to go about it is to embrace the fact and now be aware of the issues inherent in the paradigm.
what you should do (for some undefined value of "should") is keep 2 booleans around that keeps track of whether the async process should stop or not, and whether it is running or not.
These 2 bools should both be locked in the standard way. Here I will show you how:
private readonly object mSomeBooleanLock = new object(); private bool mLockedSomeBool = false; // some sane default value here
private bool SomeBoolValue() { bool result; lock(mSomeBooleanLock) { result = mLockedSomeBool; } return result; }
private void SetSomeBoolValue(bool pNewValue) { lock(mSomeBooleanLock) { mLockedSomeBool = pNewValue; } }
btw - put all of this in a new class that will "host" your background process. Then make a new instance for every new search.
Now: In this class, have methods StartBackgroundJob() and EndJob().
Startjob should look something like this: private void StartBackgroundActual(object[] pParams) { SetMustStop(false); SetIsRunning(true);
bool workIsFinished = false;
while(!MustStop() || workIsFinished) { // do some quantum of work here // use the pParams here to tune your search // sowe workIsFinished = true sometime }
if(workIsFinished) { // provide feedback with the results in some way // remember this will call on a thread different from your main ui thread // handle with care }
SetIsRunning(false); }
delegate void VoidMethod(); public void StartBackgroundJob(object[] pParams) { VoidMethod asyncCall = delegate() { StartBackgroundActual(pParams); }; asyncCall.BeginInvoke( 1, delegate(IAsyncResult pAsyncResult) { asyncCall.EndInvoke(pAsyncResult); }, null); }
public void Endjob(bool pMustBlock) { SetMustStop(true); if (pMustBlock) { while(IsRunning()) { Thread.Sleep(350); // some random value... don't set it to some power of 2. cannot remember why exactly anymore } } }
Everytime that your user changes his search parameters, set the old background job (of which you kept a handle around) to stop. Then instantiate a new instance, set it to start running with the new parameters received from the user.
I would seriously suggest that you read this piece: http://www.yoda.arachsys.com/csharp/threads/index.shtml
It is the canonical work on multi-threading (free and available online)
The other piece of advice that helped me when i learned to thread was this: investigate anonymous methods with the aim of using them for closures. The technique helps THIIIIIIIIIIS much when you are coding to different threads.
Regards, Pieter
> I do not think that will work. Here's code snippets: > private CountDelegate dDeleg; [quoted text clipped - 55 lines] > > Hope this helps, > > John Kalyan - 08 Nov 2007 14:42 GMT Hi Pieter,
I realize i am replying to a pretty old discussion thread. But i am facing an asynchronous issue and of all the replies in the discussion board, i felt yours was the most sensible one. I thought maybe you can give me some pointers for my issue.
I have to make multiple calls (about 400K) to a webservice which returns a string. And currently it takes about a week to make all the calls. Instead of waiting for the webservice result before i make the next call, I rather want to make the calls and let the results comeback at its own pace. I used Asynchronous calling and callback method, but it does not seems to work. I am sure, asynchronous way will improve my program execution exponentially. I would appreciate if someone can help me with this. And by the way, i did not see an Begin and End methods.
Here is my method which is making the webservice calls.
public static Boolean WebServiceCallsXY(string x, string y) { try { UsernameToken token = new UsernameToken("AAA", "BBB", PasswordOption.SendPlainText); MbrSrvWse wseProxy = new MbrSrvWse (); wseProxy.SetClientCredential<UsernameToken>(token); wseProxy.SetPolicy("ProvideUsernameToken");
IndividualDetailRequest test = new IndividualDetailRequest(); test.UserId = x; test.Pin = y; IndividualDetailResponse response = wseProxy.IndividualDetail(test);
if (response.Result.Length > 0) { if (response.Result.ToString().ToLower().Equals("a")) { return true; } if (response.Result.ToString().ToLower().Equals("b")) { return false; } } return false; } catch (Exception e) { Console.WriteLine("The following error '{0}' -------- {1} : {2} ", e.Message, e.StackTrace, x); return false; } }
 Signature Kalyan
> Hi Susan, > [quoted text clipped - 170 lines] > > > Hope this helps, > > > John Jon Skeet [C# MVP] - 12 Nov 2007 19:41 GMT > I realize i am replying to a pretty old discussion thread. But i am facing > an asynchronous issue and of all the replies in the discussion board, i felt [quoted text clipped - 9 lines] > would appreciate if someone can help me with this. And by the way, i did not > see an Begin and End methods. The proxy generated for the web service should have the BeginXXX and EndXXX methods. However, if you have problems with that sort of operation you could just use the ThreadPool and QueueUserWorkItem, then make the call synchronously there.
 Signature Jon Skeet - <skeet@pobox.com> http://www.pobox.com/~skeet Blog: http://www.msmvps.com/jon.skeet If replying to the group, please do not mail me too
John Duval - 03 Aug 2006 11:53 GMT Hi Susan, I see what you're asking now... I was thrown off when you said you were starting a 'process' asynchronously. :)
I agree with what the others have posted -- have the long-running operation periodically check to see if it should stop. This can done by a shared boolean flag, signalling an event, etc...
John
> I do not think that will work. Here's code snippets: > private CountDelegate dDeleg; [quoted text clipped - 55 lines] > > Hope this helps, > > John Michael Nemtsev - 02 Aug 2006 19:55 GMT Hello Susan,
Theoretically you can dive into message sing objects that are performing async calls where is the cancellation located but practically it's very hard to do, you need to intercept calls, context and etc.
standarc acyns handler classes don't have functionality to cancell async call
S> I have a process that takes a while to run so I have it running S> asynchronously so that the user can continue working. My question is S> that I want to killl the process if the user changes the search S> parameters before the callback method is called. Any ideas of how to S> do this or if it even matters? I did not know if calling the asynch S> process a new time kills the previous one or not. S> S> Thank you for your help. S> Susan --- WBR, Michael Nemtsev :: blog: http://spaces.msn.com/laflour
"At times one remains faithful to a cause only because its opponents do not cease to be insipid." (c) Friedrich Nietzsche
Susan - 02 Aug 2006 21:18 GMT Darn. I was hoping there was an easy work around. I guess I'll change it to a thread then.... Thank you. :)
> Hello Susan, > [quoted text clipped - 20 lines] > "At times one remains faithful to a cause only because its opponents do not > cease to be insipid." (c) Friedrich Nietzsche Carl Daniel [VC++ MVP] - 03 Aug 2006 00:09 GMT > Darn. I was hoping there was an easy work around. I guess I'll change it > to a > thread then.... Thank you. :) It's no easier using a Thread of your own than doing work in a method invoked by an async delegate. The reason it's no easier - you DON'T want to use Thread.Abort() to kill your worker thread. Rather, in either case (your thread or async delegate), you need to send a "message" to your long-running operation requesting that it stop. That "message" is typically just a shared bool variable (as the excellent response by Pieter Breed outlines), but it could also be a window message, a post to a Win32 Event or Semaphore, or whatever is appropriate for the task at hand. Your long-running operation then cooperatively stops when it's asked to, and sends a "message" back to the requestor acknowledging the stop request.
-cd
Susan - 03 Aug 2006 21:49 GMT Since the same process, but with different parameters would be started causing the need to stop the previous process. Basically, the user would click on one item to get the results and then change their mind and click on another item. How do I differentiate or make sure the one is stopped before I start the next one? The part of the process that takes the time is waiting for the result back from the database. Do I just do a while not complete (or back from the database at least) wait to send the second set of info? The chance is very small that the user would change their mind quickly enough for the database to not have returned, but do not want to take chances if you know what I mean. :)
Thank you, Susan
> It's no easier using a Thread of your own than doing work in a method > invoked by an async delegate. The reason it's no easier - you DON'T want to [quoted text clipped - 8 lines] > > -cd Pieter Breed - 04 Aug 2006 05:43 GMT Hi Susan,
Actually you don't /really/ need to stop the old database query at all. It can simply finish processing and return to a place where nobody is interested in its results anymore.
As long as you represent your queries as seperate class instances, and keep a reference only to the last query (and as long as those threads actually do finish!) you can simply keep on waiting for the last query to finish.
If you are talking about a db query, there isn't really any efficient way in which you can interrupt the query, since the query is running on another physical machine. (Contrast this to a filesystem search which is local and slow) If the queries are as quick as you say, then simply letting them finish won't really cost you much either.
Hope this helps, Pieter
> Since the same process, but with different parameters would be started > causing the need to stop the previous process. Basically, the user would [quoted text clipped - 9 lines] > Thank you, > Susan
Free MagazinesGet these publications absolutely FREE for up to 12 months. There are no hidden fees and no obligation. Simply choose a title, complete the application form and submit it. Read more ...
|
|
|