Quick Multithreading Question - c#

I have a startup function that calls a function which returns a boolean based on whether the set up is successful or not. True if successful, false if failed. I would like to start that function on a new thread and then check the status of the function: here is the code.
System.Threading.Thread thread = new System.Threading.Thread(new System.Threading.ThreadStart(StartAdapter));
thread.Start();
My question is, how in that case would I check the return status of the startadapter method? Because my friend told me that I will not know the return status because it is started on another thread, and yet trying:
System.Threading.Thread thread = new System.Threading.Thread(new System.Threading.ThreadStart(StartAdapter));
thread.Start();
bool result = StartAdapter();
would call the function twice, which is something I don't want either. Does anybody have some insight into this?
How in this case would I check the boolean returned from the startadapter function?
.NET 3.5

for this case there is the Task<T> class that executes on the ThreadPool (for example) and lets you know the return value after it's finished
just use:
var task = TaskFactory&ltyourResultType&gt.StartNew(StartAdapter);
Action&ltyourResultType&gt actionAfterResult = ...; // whatever you have to do
task.ContinueWith(actionAfterResult);
// or:
var result = task.Result; // this will block till the result is computed
// or another one of the alternatives you can learn about on MSDN (see link above)

Related

How to set a property if the value is in another thread

I want set a property where the value is in another thread
[DllExport]
public static bool Value()
{
bool val = false;
Thread thread = new Thread(async () => val = await getVal());
thread.IsBackground = true;
thread.SetApartmentState(ApartmentState.STA);
thread.Start();
return val;
}
public async Task<bool> getVal()
{
bool value = false;
await Task.Factory.StartNew(() =>
{
string rs = new WebClient().DownloadString(url);
if (rs == "1")
value = true;
else
value = false;
});
return value;
}
It always returns false why I use that one is I cant use await in a static [DLLExport] method otherwise the form will freeze.
Edit: I cant use async in a DllExport method
Well starting the Thread really tells you nothing about when the code is being run.
After you call .Start() you tell the thread to run its code, but you have no real control of when the OS decides to actually let the code run.
Im also not sure how using locally defined variables inside the other thread-scope actually works, but I find it hard to think that you can set the value like you are trying to do.
Try googling Monitor.Wait(), Monitor.Pulse() which can be used to let one thread wait for another to finish (one calls Monitor.Wait() and the other calls Monitor.Pulse() when it wants the waiting thread to start executing).

C# wait for thread to complete before continuing

I have the following simplified code:
object myVariable;
var myThread = new Thread(async () =>
{
//Do something....
myVariable = //Some result....
});
myThread.Start();
I start myThread on the first line of my method. My understanding is that this thread will then go off and execute, whilst the rest of the method executes simultaneously. Is this correct?
I then reach a point further down in my code where I will use myVariable. Given this, I need my main thread to pause if myThread has not completed.
My understanding is that I can use myThread.Join() to do this. However, once I call .Join it will pause the main thread until myThread has completed.
My question is, if I do this:
Start myThread
THEN
execute other code that takes x seconds
THEN
Call myThread.Join()
In this case, will the join not happen until it reaches that line of code eg join will not take place until after x seconds - or does join look ahead?
I hope this question is clear?
I don't know if I'm understanding correctly, but I'll try to answer you.
To do what you want, you can use something like:
await someMethod().ContinueWith((task) =>
{
someOtherMethodThatUsesTaskResult(task.Result);
//more code
}, TaskContinuationOptions.OnlyOnRanToCompletion);
Of course you can explore the options you have available for the last parameter.
In your case you can use the keyword await (I think for your situation it's better) :
var myTask = asyncTask(); // Launch the Task
// execute other code that takes x seconds
var myVariable = await myTask; // Get the result of the Task (and wait if it was not finished)

Await in static method

I have a method that I use to get string from web service
I started the code with
var task = _tempClient.GetteststringAsync();
string teststring = await task;
but I noticed that the code not wait till the call end and the value retrieved ,so I tried something like
string teststring= string.Empty;
var t1 = Task.Factory.StartNew(new Func<Task>(async () => teststring= await _tempClient.GetteststringAsync()))
.Unwrap();
t1.Wait();
but this cause the application stuck , any idea how to make it work ,tempClient is a service refrence object . I use it to intialise the webrefrence in MVC Application, it's the helper class
Your first attempt was much closer to doing the right thing, calling task.Wait() or task.Result is a blocking call and can often cause a deadlock. Have a look at this article for async/await best practices.
What you want to do is what you had first:
var task = _tempClient.GetteststringAsync();
string teststring = await task;
Calling _tempClient.GetteststringAsync() will start executing on a thread pool thread and once finished the result will be returned into teststring and the rest of the method will execute on the original request thread. At that point you just need to do whatever you need to with teststring.
I solved it using
http://blogs.msdn.com/b/pfxteam/archive/2012/01/20/10259049.aspx using this code looks like
AsyncPump.Run(async delegate
{
await DemoAsync();
});

BeginGetResponse in web application

I want to use the BeginGetResponse method in order to call many URLs which I hold on a list.
I have 2 questions on how to implement this:
according to the example in http://msdn.microsoft.com/en-us/library/system.net.httpwebrequest.begingetresponse(v=vs.95).aspx
we use:
public static ManualResetEvent allDone= new ManualResetEvent(false);
is that wise to use a static member in web application since it's shared with other threads ? can this cause for problems ?
how can I tell when all the callbacks were finished ? I need to do a summary report on the results
Thanks
While you can use an event, I'd recommend using Task<T> and the FromAsync method on the TaskFactory class like so:
// Execution of tasks starts here because of the
// call to ToArray.
Task<WebResponse>[] tasks = uris.Select(u => {
// Create the request.
WebRequest req = ...;
// Make the call to return the response asynchronously with
// a Task.
return Task.Factory.FromAsync(req.BeginGetResponse,
req.EndGetResponse, null);
}).ToArray();
Once you have that, you can easily wait on all of the Task<T> instances using the ContinueWhenAll method on the TaskFactory class like so with a continuation:
Task.Factory.ContinueWhenAll(tasks, t => {
// Note that t is an array of Task, so you have to cast
// each element to a Task<WebRequest>.
// Process all of them here.
});
Note the above returns a Task which you will have to wait on or continued on when done (if your're concerned about the notification).
If you are using .NET 4.5, you don't need to use the ContinueWhenAll method on the TaskFactory class, but can use the WhenAll method on the Task class to perform the work:
// Note that work does not start here yet because of deferred execution.
// If you want it to start here, you can call ToArray like above.
IEnumerable<Task<WebResponse>> tasks = uris.Select(u => {
// Create the request.
WebRequest req = ...;
// Make the call to return the response asynchronously with
// a Task.
return Task.Factory.FromAsync(req.BeginGetResponse,
req.EndGetResponse, null);
});
// Execution will start at this call:
Task<Task<WebRequest>[]> allTasks = Task.WhenAll(tasks);
// Continue or wait here.
Note that the above was before it was revealed that .NET 3.5 was being used.
If you want to wait in main thread for completition, then this solution is not very good. First request will change event's state to "set". Therefore, main thread will continue execution after the first request completed.
A suggest you to use CountdownEvent:
using(var countdownEvent = new CountdownEvent(list.Count))
{
// launch requests with countdownEvent.Signal(); in the end
countdownEvent.Wait();
}
You must store reference to countdownEvent inside RequestState. Also, don't forget to control timeouts - start new thread with ThreadPool.RegisterWaitForSingleObject.
I guess you're trying to do something like this:
int total = urls.Count;
ManualResetEvent evt = new ManualResetEvent();
ConcurrentBag<WebResponses> responses = new ConcurrentBag<WebResponse>();
foreach(Uri in uri)
{
HttpWebRequest req = ...;
req.BeginGetResponse(res=>
{
WebResponse res = req.EndGetResponse();
// do what you need with the response.
// maybe add it to a collection so you can report on it later:
responses.Add(res);
if(Interlocked.Decrement(ref total) == 0)
{
// this was the last response. set event.
evt.Set();
}
}, null);
}
evt.Wait();
foreach(WebResponse res in responses)
{
// report something about the response.
}
Note that an optimal workflow will not need an event. For extra credit, get rid of it all together and move your final logic inside the if that sets the event.
Also, this code is untested and lacks error handling, so be sure to add that in if you play with it at all.

Threading methods from other classes?

There is a method that is called continuously in my program and so I want to thread it such that the GUI doesn't freeze whilst it goes about its business.
Thread t = new Thread(Class2.ArrayWorkings(1, MyGlobals.variable1));
t.start();
int[] localVariable1 = ??// I want to move the value returned from the method into localVariable1.
Currently my errors are:
The best overloaded method match for 'System.Threading.Thread.Thread(System.Threading.ParameterizedThreadStart)' has some invalid arguments
&
Argument 1: cannot convert from 'method group' to 'System.Threading.ParameterizedThreadStart'
Currently doing this without threading like:
int[] localVariabl1 = Class2.ArrayWorkings(1, MyGlobals.variable1);
You can fix the constructor by using a lambda:
Thread t = new Thread(() => Class2.ArrayWorkings(1, MyGlobals.variable1));
but that doesn't let you (as Jon notes) get the result straight away - otherwise you are writing synchronous code again. You can instead look to some kind of callback; presumably you need to get back to the UI thread, so:
Thread t = new Thread(() => {
// this runs on the worker
int[] localVariabl1 = Class2.ArrayWorkings(1, MyGlobals.variable1);
this.Invoke((MethodInvoker)delegate {
// now we're back on the UI thread!
update the UI from localVariabl1
});
});
t.Start()
I would probably suggest using the thread-pool, though:
ThreadPool.QueueUserWorkItem(delegate {
// this runs on the worker
int[] localVariabl1 = Class2.ArrayWorkings(1, MyGlobals.variable1);
this.Invoke((MethodInvoker)delegate {
// now we're back on the UI thread!
update the UI from localVariabl1
});
});
You gotto put a ThreadStart Delegate. If you really dont want UI to get affected, u should use BackgroundWorker Class.
One way of doing it is as following:
ThreadStart starter = delegate { Class2.ArrayWorkings(1, MyGlobals.variable1); };
var thread = new Thread(starter);
thread.Start();
Edit: Just saw that you also want to capture the return value from the thread.
You may have to use ThreadPool.QueueUserWorkItem as mentioned in Marc's answer
Something you might want to look at is .NET Framework 4.5 (still in Release Candidate)
Makes life easier with Asynchronous programming.
await operator in .NET 4.5
Tasks provide an easy interface for performing an asynchronous job that will eventually return a value. A Task<string> for example is a task that (eventually) returns a string where a Task<int[]> will return an array of integers.
int[] localVariable1;
// start the task
Task<int[]> myTask = Task.Factory.StartNew<int[]>(() => Class2.ArrayWorkings(1, MyGlobals.Variable1);
// when it is finished get the result and place in local variable
myTask.OnCompleted(task => localVariable1 = task.Result;);
If you want to update a UI compontent once the asynchronous operation is finished, you will have to use Invoke (for winforms). This allows you to work with objects that live on the UI thread (such as buttons and labels).
myTask.OnCompleted(task => localVariable1.Invoke(new Action(() =>
localVariable1.Value = task.Result; )));

Categories