How do you call a generic method on a thread? - c#

How would I call a method with the below header on a thread?
public void ReadObjectAsync<T>(string filename)
{
// Can't use T in a delegate, moved it to a parameter.
ThreadStart ts = delegate() { ReadObjectAcync(filename, typeof(T)); };
Thread th = new Thread(ts);
th.IsBackground = true;
th.Start();
}
private void ReadObjectAcync(string filename, Type t)
{
// HOW?
}
public T ReadObject<T>(string filename)
{
// Deserializes a file to a type.
}

Why can't you just do this...
public void ReadObjectAsync<T>(string filename)
{
ThreadStart ts = delegate() { ReadObject<T>(filename); };
Thread th = new Thread(ts);
th.IsBackground = true;
th.Start();
}
private void ReadObject<T>(string filename)
{
// Deserializes a file to a type.
}

I assume you may have good reasons for using a free-running Thread as opposed to the .NET thread pool, but just for reference, this is quite easy to do in C# 3.5+ with the thread pool:
public void ReadObjectAsync<T>(string filename, Action<T> callback)
{
ThreadPool.QueueUserWorkItem(s =>
{
T result = ReadObject<T>(fileName);
callback(result);
});
}
I put the callback in there because I assume that you probably want to do something with the result; your original example (and the accepted answer) doesn't really provide any way to gain access to it.
You would invoke this method as:
ReadObjectAsync<MyClass>(#"C:\MyFile.txt", c => DoSomethingWith(c));

It would be easy to make this truly generic...
public void RunAsync<T, TResult>(Func<T, TResult> methodToRunAsync, T arg1,
Action<TResult> callback)
{
ThreadPool.QueueUserWorkItem(s =>
{
TResult result = methodToRunAsync(arg1);
callback(result);
});
}

Related

How to implement this pattern in C#

Class Client{
main(){
MyRequest m = new MyRequest();
m.function();
}
onSucess(string s){
Debug.log("i get data from network:"+s);
}
}
Class Network{
sendMyrequest(MyRequest r){
Thread thread = new Thread(() => sendMyrequestTask(r));
thread.start();
}
private void sendMyrequestTask(MyRequest r){
if(...){
//call delegate function onSucess(string s)
}
}
}
Class MyRequest{
private Network network;
function(){
//do something
network.sendMyrequest(MyRequest r);
}
}
in this case, callback function onSucess(string s) should be a delegate, or a interface, how and where should I implement it? Any suggestion would be appreciate. Thanks in advance!!
Edit: this problem is like: A call B,B call C, when C's job is done, C should call A. How to implement this?
Thanks all guys. I implement in this way.
public interface CallbackFunction{
public onSucess(string s);
}
Class Client:CallbackFunction{
main(){
MyRequest m = new MyRequest();
m.function(this);
}
onSucess(string s){
Debug.log("i get data from network:"+s);
}
}
Class Network{
sendMyrequest(MyRequest r,CallbackFunction c){
Thread thread = new Thread(() => sendMyrequestTask(r,c));
thread.start();
}
private void sendMyrequestTask(MyRequest r,CallbackFunction c){
if(...){
//call delegate function onSucess(string s)
c.onSucess("bla bla bla");
}
}
}
Class MyRequest{
private Network network;
function(CallbackFunction c){
//do something
network.sendMyrequest(this,c);
}
}
You can use async and `await.
For more info :
Many methods do not immediately return. A method may need to query an external source. This takes time. With async and await, we formalize and clarify how asynchronous, non-blocking methods begin and end.
http://msdn.microsoft.com/en-us/library/hh191443.aspx
http://msdn.microsoft.com/en-us/library/hh156513.aspx
By using the Action<> delegate as a constructor argument in MyRequest we can achieve something like this.
You can replace the Action<> type with any other delegate you might want to use. Action<> or Func<> should cover just about anything.
By the way, your code, and hence my code below is not the observer pattern.
public class Client
{
static void Main(string[] args)
{
var client = new MyRequest(OnSuccess);
client.Function();
//Output:
//I'm in the callback
//Foo.Bar()
Console.ReadKey();
}
static void OnSuccess(string result)
{
Console.WriteLine("I'm in the callback");
Console.WriteLine(result);
}
}
public class Network
{
public void SendMyRequest(MyRequest request)
{
var result = "Foo.Bar()";
if (!String.IsNullOrEmpty(result))
{
request.SuccessCallback(result);
}
}
}
public class MyRequest
{
public Action<string> SuccessCallback { get; private set; }
private Network _network;
public MyRequest(Action<string> successCallback)
{
_network = new Network();
SuccessCallback = successCallback;
}
public void Function()
{
_network.SendMyRequest(this);
}
}
It looks like you want to implement something similar to WebClient.DownloadStringCompleted event. Which uses following delegate type:
public delegate void DownloadStringCompletedEventHandler(
Object sender
DownloadStringCompletedEventArgs e)`
with following usage pattern:
WebClient client = new WebClient ();
client.DownloadStringCompleted += DownloadStringCallback2;
client.DownloadStringAsync (new Uri(address));
Note: if you don't expect multiple listeners using async/await will lead to much easier to understand code.

C# - Start new thread calling parameter method [duplicate]

How do you start a thread with parameters in C#?
One of the 2 overloads of the Thread constructor takse a ParameterizedThreadStart delegate which allows you to pass a single parameter to the start method. Unfortunately though it only allows for a single parameter and it does so in an unsafe way because it passes it as object. I find it's much easier to use a lambda expression to capture the relevant parameters and pass them in a strongly typed fashion.
Try the following
public Thread StartTheThread(SomeType param1, SomeOtherType param2) {
var t = new Thread(() => RealStart(param1, param2));
t.Start();
return t;
}
private static void RealStart(SomeType param1, SomeOtherType param2) {
...
}
Yep :
Thread t = new Thread (new ParameterizedThreadStart(myMethod));
t.Start (myParameterObject);
You can use lambda expressions
private void MyMethod(string param1,int param2)
{
//do stuff
}
Thread myNewThread = new Thread(() => MyMethod("param1",5));
myNewThread.Start();
this is so far the best answer i could find, it's fast and easy.
Simple way using lambda like so..
Thread t = new Thread(() => DoSomething("param1", "param2"));
t.Start();
OR you could even delegate using ThreadStart like so...
private void DoSomething(int param1, string param2)
{
//DO SOMETHING...
ThreadStart ts = delegate
{
if (param1 > 0) DoSomethingElse(param2, "param3");
};
new Thread(ts).Start();
//DO SOMETHING...
}
OR using .NET 4.5+ even cleaner like so..
private void DoSomething(int param1, string param2)
{
//DO SOMETHING..
void ts()
{
if (param1 > 0) DoSomethingElse(param2, "param3");
}
new Thread(ts).Start();
//DO SOMETHING..
}
Thread thread = new Thread(Work);
thread.Start(Parameter);
private void Work(object param)
{
string Parameter = (string)param;
}
The parameter type must be an object.
EDIT:
While this answer isn't incorrect I do recommend against this approach. Using a lambda expression is much easier to read and doesn't require type casting. See here: https://stackoverflow.com/a/1195915/52551
class Program
{
static void Main(string[] args)
{
Thread t = new Thread(new ParameterizedThreadStart(ThreadMethod));
t.Start("My Parameter");
}
static void ThreadMethod(object parameter)
{
// parameter equals to "My Parameter"
}
}
As has already been mention in various answers here, the Thread class currently (4.7.2) provides several constructors and a Start method with overloads.
These relevant constructors for this question are:
public Thread(ThreadStart start);
and
public Thread(ParameterizedThreadStart start);
which either take a ThreadStart delegate or a ParameterizedThreadStart delegate.
The corresponding delegates look like this:
public delegate void ThreadStart();
public delegate void ParameterizedThreadStart(object obj);
So as can be seen, the correct constructor to use seems to be the one taking a ParameterizedThreadStart delegate so that some method conform to the specified signature of the delegate can be started by the thread.
A simple example for instanciating the Thread class would be
Thread thread = new Thread(new ParameterizedThreadStart(Work));
or just
Thread thread = new Thread(Work);
The signature of the corresponding method (called Work in this example) looks like this:
private void Work(object data)
{
...
}
What is left is to start the thread. This is done by using either
public void Start();
or
public void Start(object parameter);
While Start() would start the thread and pass null as data to the method, Start(...) can be used to pass anything into the Work method of the thread.
There is however one big problem with this approach:
Everything passed into the Work method is cast into an object. That means within the Work method it has to be cast to the original type again like in the following example:
public static void Main(string[] args)
{
Thread thread = new Thread(Work);
thread.Start("I've got some text");
Console.ReadLine();
}
private static void Work(object data)
{
string message = (string)data; // Wow, this is ugly
Console.WriteLine($"I, the thread write: {message}");
}
Casting is something you typically do not want to do.
What if someone passes something else which is not a string? As this seems not possible at first (because It is my method, I know what I do or The method is private, how should someone ever be able to pass anything to it?) you may possibly end up with exactly that case for various reasons. As some cases may not be a problem, others are. In such cases you will probably end up with an InvalidCastException which you probably will not notice because it simply terminates the thread.
As a solution you would expect to get a generic ParameterizedThreadStart delegate like ParameterizedThreadStart<T> where T would be the type of data you want to pass into the Work method. Unfortunately something like this does not exist (yet?).
There is however a suggested solution to this issue. It involves creating a class which contains both, the data to be passed to the thread as well as the method that represents the worker method like this:
public class ThreadWithState
{
private string message;
public ThreadWithState(string message)
{
this.message = message;
}
public void Work()
{
Console.WriteLine($"I, the thread write: {this.message}");
}
}
With this approach you would start the thread like this:
ThreadWithState tws = new ThreadWithState("I've got some text");
Thread thread = new Thread(tws.Work);
thread.Start();
So in this way you simply avoid casting around and have a typesafe way of providing data to a thread ;-)
I was having issue in the passed parameter.
I passed integer from a for loop to the function and displayed it , but it always gave out different results. like (1,2,2,3) (1,2,3,3) (1,1,2,3) etc with ParametrizedThreadStart delegate.
this simple code worked as a charm
Thread thread = new Thread(Work);
thread.Start(Parameter);
private void Work(object param)
{
string Parameter = (string)param;
}
The ParameterizedThreadStart takes one parameter. You can use that to send one parameter, or a custom class containing several properties.
Another method is to put the method that you want to start as an instance member in a class along with properties for the parameters that you want to set. Create an instance of the class, set the properties and start the thread specifying the instance and the method, and the method can access the properties.
You could use a ParametrizedThreadStart delegate:
string parameter = "Hello world!";
Thread t = new Thread(new ParameterizedThreadStart(MyMethod));
t.Start(parameter);
You can use the BackgroundWorker RunWorkerAsync method and pass in your value.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Threading;
namespace ConsoleApp6
{
class Program
{
static void Main(string[] args)
{
int x = 10;
Thread t1 =new Thread(new ParameterizedThreadStart(order1));
t1.IsBackground = true;//i can stope
t1.Start(x);
Thread t2=new Thread(order2);
t2.Priority = ThreadPriority.Highest;
t2.Start();
Console.ReadKey();
}//Main
static void order1(object args)
{
int x = (int)args;
for (int i = 0; i < x; i++)
{
Console.ForegroundColor = ConsoleColor.Green;
Console.Write(i.ToString() + " ");
}
}
static void order2()
{
for (int i = 100; i > 0; i--)
{
Console.ForegroundColor = ConsoleColor.Red;
Console.Write(i.ToString() + " ");
}
}`enter code here`
}
}
I propose using Task<T>instead of Thread; it allows multiple parameters and executes really fine.
Here is a working example:
public static void Main()
{
List<Task> tasks = new List<Task>();
Console.WriteLine("Awaiting threads to finished...");
string par1 = "foo";
string par2 = "boo";
int par3 = 3;
for (int i = 0; i < 1000; i++)
{
tasks.Add(Task.Run(() => Calculate(par1, par2, par3)));
}
Task.WaitAll(tasks.ToArray());
Console.WriteLine("All threads finished!");
}
static bool Calculate1(string par1, string par2, int par3)
{
lock(_locker)
{
//...
return true;
}
}
// if need to lock, use this:
private static Object _locker = new Object();"
static bool Calculate2(string par1, string par2, int par3)
{
lock(_locker)
{
//...
return true;
}
}
A very simple and convenient way using lambda expression can be like this:
Thread thread = new Thread( (param) => {
string name = param as string;
// rest of code goes here.
});
thread.Start("MyName");
This way a lambda expression can have parameters and run inline code in a separate thread.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Threading;
namespace ConsoleApp6
{
class Program
{
static void Main(string[] args)
{
int x = 10;
Thread t1 =new Thread(new ParameterizedThreadStart(order1));
t1.Start(x);
Thread t2=new Thread(order2);
t2.Priority = ThreadPriority.Highest;
t2.Start();
Console.ReadKey();
}//Main
static void order1(object args)
{
int x = (int)args;
for (int i = 0; i < x; i++)
{
Console.ForegroundColor = ConsoleColor.Green;
Console.Write(i.ToString() + " ");
}
}
static void order2()
{
for (int i = 100; i > 0; i--)
{
Console.ForegroundColor = ConsoleColor.Red;
Console.Write(i.ToString() + " ");
}
}
}
}

Pass Parameters through ParameterizedThreadStart

I'm trying to pass parameters through the following:
Thread thread = new Thread(new ParameterizedThreadStart(DoMethod));
Any idea how to do this? I'd appreciate some help
lazyberezovsky has the right answer. I want to note that technically you can pass an arbitrary number of arguments using lambda expression due to variable capture:
var thread = new Thread(
() => DoMethod(a, b, c));
thread.Start();
This is a handy way of calling methods that don't fit the ThreadStart or ParameterizedThreadStart delegate, but be careful that you can easily cause a data race if you change the arguments in the parent thread after passing them to the child thread's code.
Use overloaded Thread.Start method, which accepts object (you can pass your custom type or array if you need several parameters):
Foo parameter = // get parameter value
Thread thread = new Thread(new ParameterizedThreadStart(DoMethod));
thread.Start(parameter);
And in DoMethod simply cast argument to your parameter type:
private void DoMethod(object obj)
{
Foo parameter = (Foo)obj;
// ...
}
BTW in .NET 4.0 and above you can use tasks (also be careful with race conditions):
Task.Factory.StartNew(() => DoMethod(a, b, c));
Instead of creating a class to pass in multiple parameters as #user1958681 has done, you could use anonymous types, then just use the dynamic typing to extract your parameters.
class MainClass
{
int A = 1;
string B = "Test";
Thread ActionThread = new Thread(new ParameterizedThreadStart(DoWork));
ActionThread.Start(new { A, B});
}
Then in DoWork
private static void DoWork(object parameters)
{
dynamic d = parameters;
int a = d.A;
string b = d.B;
}
Another way to archive what you want, is by returning a delegate within your function / method. Take the following example:
class App
{
public static void Main()
{
Thread t = new Thread(DoWork(a, b));
t.Start();
if (t.IsAlive)
{
t.IsBackground = true;
}
}
private static ThreadStart DoWork(int a, int b)
{
return () => { /*DoWork*/ var c = a + b; };
}
}
new Thread(() => { DoMethod(a, b, c); }).Start();
or
new Thread(() => DoMethod(a, b, c)).Start();
// Parameters to pass to ParameterizedThreadStart delegate
// - in this example, it's an Int32 and a String:
class MyParams
{
public int A { get; set; }
public string B { get; set; }
// Constructor
public MyParams(int someInt, string someString)
{
A = someInt;
B = someString;
}
}
class MainClass
{
MyParams ap = new MyParams(10, "Hello!");
Thread t = new Thread(new ParameterizedThreadStart(DoMethod));
t.Start(ap); // Pass parameters when starting the thread
}
class Program
{
public static void Main()
{
MyClass myClass = new MyClass();
ParameterizedThreadStart pts = myClass.DoMethod;
Thread thread1 = new Thread(pts);
thread1.Start(20); // Pass the parameter
Console.Read();
}
}
class MyClass
{
private int Countdown { get; set; }
public void DoMethod(object countdown) // Parameter must be an object and method must be void
{
Countdown = (int) countdown;
for (int i = Countdown; i > 0; i--)
{
Console.WriteLine("{0}", i);
}
Console.WriteLine("Finished!");
}
}

How to make an Asynchronous Method return a value?

I know how to make Async methods but say I have a method that does a lot of work then returns a boolean value?
How do I return the boolean value on the callback?
Clarification:
public bool Foo(){
Thread.Sleep(100000); // Do work
return true;
}
I want to be able to make this asynchronous.
From C# 5.0, you can specify the method as
public async Task<bool> doAsyncOperation()
{
// do work
return true;
}
bool result = await doAsyncOperation();
There are a few ways of doing that... the simplest is to have the async method also do the follow-on operation. Another popular approach is to pass in a callback, i.e.
void RunFooAsync(..., Action<bool> callback) {
// do some stuff
bool result = ...
if(callback != null) callback(result);
}
Another approach would be to raise an event (with the result in the event-args data) when the async operation is complete.
Also, if you are using the TPL, you can use ContinueWith:
Task<bool> outerTask = ...;
outerTask.ContinueWith(task =>
{
bool result = task.Result;
// do something with that
});
Use a BackgroundWorker. It will allow you to get callbacks on completion and allow you to track progress. You can set the Result value on the event arguments to the resulting value.
public void UseBackgroundWorker()
{
var worker = new BackgroundWorker();
worker.DoWork += DoWork;
worker.RunWorkerCompleted += WorkDone;
worker.RunWorkerAsync("input");
}
public void DoWork(object sender, DoWorkEventArgs e)
{
e.Result = e.Argument.Equals("input");
Thread.Sleep(1000);
}
public void WorkDone(object sender, RunWorkerCompletedEventArgs e)
{
var result = (bool) e.Result;
}
Probably the simplest way to do it is to create a delegate and then BeginInvoke, followed by a wait at some time in the future, and an EndInvoke.
public bool Foo(){
Thread.Sleep(100000); // Do work
return true;
}
public SomeMethod()
{
var fooCaller = new Func<bool>(Foo);
// Call the method asynchronously
var asyncResult = fooCaller.BeginInvoke(null, null);
// Potentially do other work while the asynchronous method is executing.
// Finally, wait for result
asyncResult.AsyncWaitHandle.WaitOne();
bool fooResult = fooCaller.EndInvoke(asyncResult);
Console.WriteLine("Foo returned {0}", fooResult);
}
Perhaps you can try to BeginInvoke a delegate pointing to your method like so:
delegate string SynchOperation(string value);
class Program
{
static void Main(string[] args)
{
BeginTheSynchronousOperation(CallbackOperation, "my value");
Console.ReadLine();
}
static void BeginTheSynchronousOperation(AsyncCallback callback, string value)
{
SynchOperation op = new SynchOperation(SynchronousOperation);
op.BeginInvoke(value, callback, op);
}
static string SynchronousOperation(string value)
{
Thread.Sleep(10000);
return value;
}
static void CallbackOperation(IAsyncResult result)
{
// get your delegate
var ar = result.AsyncState as SynchOperation;
// end invoke and get value
var returned = ar.EndInvoke(result);
Console.WriteLine(returned);
}
}
Then use the value in the method you sent as AsyncCallback to continue..
You should use the EndXXX of your async method to return the value. EndXXX should wait until there is a result using the IAsyncResult's WaitHandle and than return with the value.

Asynchronous programming design pattern

I'm working on a little technical framework for CF.NET and my question is, how should I code the asynchronous part? Read many things on MSDN but isn't clear for me.
So, here is the code :
public class A
{
public IAsyncResult BeginExecute(AsyncCallback callback)
{
// What should I put here ?
}
public void EndExecute()
{
// What should I put here ?
}
public void Execute()
{
Thread.Sleep(1000 * 10);
}
}
If someone can help me...
Thanks !
You could use a delegate:
public class A
{
public void Execute()
{
Thread.Sleep(1000 * 3);
}
}
class Program
{
static void Main()
{
var a = new A();
Action del = (() => a.Execute());
var result = del.BeginInvoke(state =>
{
((Action)state.AsyncState).EndInvoke(state);
Console.WriteLine("finished");
}, del);
Console.ReadLine();
}
}
UPDATE:
As requested in the comments section here's a sample implementation:
public class A
{
private Action _delegate;
private AutoResetEvent _asyncActiveEvent;
public IAsyncResult BeginExecute(AsyncCallback callback, object state)
{
_delegate = () => Execute();
if (_asyncActiveEvent == null)
{
bool flag = false;
try
{
Monitor.Enter(this, ref flag);
if (_asyncActiveEvent == null)
{
_asyncActiveEvent = new AutoResetEvent(true);
}
}
finally
{
if (flag)
{
Monitor.Exit(this);
}
}
}
_asyncActiveEvent.WaitOne();
return _delegate.BeginInvoke(callback, state);
}
public void EndExecute(IAsyncResult result)
{
try
{
_delegate.EndInvoke(result);
}
finally
{
_delegate = null;
_asyncActiveEvent.Set();
}
}
private void Execute()
{
Thread.Sleep(1000 * 3);
}
}
class Program
{
static void Main()
{
A a = new A();
a.BeginExecute(state =>
{
Console.WriteLine("finished");
((A)state.AsyncState).EndExecute(state);
}, a);
Console.ReadLine();
}
}
You don't need to do anything special, cause the caller should call you method async,
He define a new delegate pointing to you method, and use the .net to call your method asynchronously.
On BeginExecute you have to start the asynchronous operation (possibly start execute in a separate thread) and return as quick as possible. Execute has to call the AsyncCallback at the end of all operations so that who use the async operation gets aware and get the result. EndExecute has to stop a previously started async operation (possibly interrupting the thread launched by BeginExecute).
Without more details this is the best I can do.
If you want to run piece of code asynchronously, you should use BackgroundWorker. Unless of course, the code you are calling doesn't support asynchronous operation natively. Just like Read/Write methods or service calls.
If you want to notify, that the asynchronous operation has finished, use delegate or event callback.

Categories