Suppose I have a List<Task>:
private readonly List<Task> _tasks = new List<Task>(new Task[9]);
I want create a Task for start the DoWorkAsync method available inside the class Foo, so what I did is the following:
_tasks[0] = new Task<Foo>(() => new Foo().DoWorkAsync());
so the Foo class contains DoWorkAsync method which have a design similar to this:
public async Task HeavyAsync()
{
while (true)
{
string newData = DateTime.Now.ToLongTimeString();
Console.WriteLine(newData);
await Task.Delay(200);
}
}
actually I can start the Task using _tasks[0].Start();.
This works, but the main problem is that I want access to the public property of Foo class and I can't, because when I type this: _tasks[0].
I'll get the following method:
I also tried using GetAwaiter() and await:
var foo = await _tasks[0];
but I'll get the following error:
Cannot assign void to an implicitly-typed local variable
How can I access to the Foo properties?
You have to change the interface of your method. A task is just a "function pointer" that is executed and then finished. If you need the object, that contains the executed function, then you have to save or return it somewhere.
I would do the following: change the async method to return an object like:
public async Task<Foo> HeavyAsync()
{
while (true)
{
string newData = DateTime.Now.ToLongTimeString();
Console.WriteLine(newData);
await Task.Delay(200);
}
return this;
}
then this statement
var foo = await _tasks[0];
should give you with foo a reference to your Foo-object.
UPDATE:
Or you give your class Foo the following property and methods:
class Foo
{
private Task runningTask {get;set;}
public void StartTask()
{
runningTask = Task.Start( () => ....);
}
public async Task WaitTask()
{
await runningTask;
}
public bool IsRunning => runningTask != null && runningTask.Status......
And instead of holding a list of Task in your calling method, you might hold the list of Foo instances.
Related
I have a func delegate that is defined as follows,
public enum RunEndStatus
{
Success
}
public class classA
{
Func<object, RunEndStatus> ProcessCalibrationRun { get; set; }
}
Now in an other class lets say classB I am doing something like this,
public class ClassB
{
public void DoSomething()
{
ClassA a = new ClassA();
a.ProcessCalibrationRun = ProcessCalibrationRun;//This is just fine. It won't complain here.
}
public RunEndStatus ProcessCalibrationRun(object obj)
{
//Here I have some piece of code takes so much time. To replicate it,
Thread.Sleep(10000);
}
}
When the DoSomething method is called from somewhere, the application blocks for 10 minutes.So I am trying to fix my problem as follows,
public async Task<RunEndStatus> ProcessCalibrationRun(object obj)
{
await Task.Run(() => { Thread.Sleep(10000)});
return RunEndStatus.Success;
}
I am modifying the call as follows. But it says cannot await method group. Please help how can I await on that method.
public async void DoSomething()
{
ClassA a = new ClassA();
a.ProcessCalibrationRun = await ProcessCalibrationRun; //Here it complains saying cannot await method group.
}
An async signature returns a Task, so your Func will need to as well
public Func<object, Task<RunEndStatus>> ProcessCalibrationRun { get; set; }
Meaning you will not need the async signature in your DoSomething, which should not be async void anyway
public void DoSomething()
{
vara = new ClassA();
a.ProcessCalibrationRun = ProcessCalibrationRun;
}
Then somewhere else (perhaps in ClassA) you can invoke it
public async Task DoSomethingElse()
{
await ProcessCalibrationRun(somethignObject);
}
Please consider code below. Each time I run the code, output will be always 0 and 3. I am sure it has something to do with single instance but didn't have any explanation why this is happening. It will be great if you can help me understand this. Thank you for your help.
Is this happening because variable points to a different location in heap each time we initialize it ?
public class Helper
{
List<int> list = new List<int>();
public List<int> GetList
{
get
{
return list;
}
}
public async Task<bool> Process()
{
await Task.Delay(1);
//sleep this thread for 6 seconds
Thread.Sleep(6000);
//When I debug, both of the thread adds into the list
//but first thread always have zero element on this list, if it adds to the list then where it is getting lost ?
//not sure why ? Has to do something with the variable below _confighelper
//but why it behaves likes this ? what would be the best explanation?
//where this variable is getting lost ?
list.Add(1);
list.Add(2);
list.Add(3);
return true;
}
}
public class RunOp
{
//Has to do something with single instance
Helper _configHelper;
public async Task Run()
{
_configHelper = new Helper();
var val = await _configHelper.Process();
Console.WriteLine(_configHelper.GetList.Count);
}
}
class Program
{
static void Main(string[] args)
{
RunOp op = new RunOp();
Task.Factory.StartNew(async () =>
{
await op.Run();
});
Thread.Sleep(4000);
//Start another thread after 4 seconds
Task.Factory.StartNew(async () =>
{
await op.Run();
});
Console.ReadLine();
}
}
This is a simple case of thread safety, and this is not thread safe
The problem is RunOp has an internal Helper, which gets overwritten and showing (what seems) inconsistent results because of the thread sleeps and delays.
Here is a thread safe version
public class RunOp
{
private SemaphoreSlim slim = new SemaphoreSlim(1,1);
//Has to do something with single instance
Helper _configHelper;
public async Task Run()
{
await slim.WaitAsync();
_configHelper = new Helper();
var val = await _configHelper.Process();
Console.WriteLine(_configHelper.GetList.Count);
slim.Release();
}
// or
public async Task Run()
{
Helper configHelper = new Helper();
var val = await configHelper.Process();
Console.WriteLine(configHelper.GetList.Count);
}
}
I know this is only an academic problem, but this really should be refactored and thought through again
This is a confusing matter for me, hope to describe it correctly.
This is in a Xamarin.Android project:
I have a class like this (simplified):
public class FinishedListener : Java.Lang.Object, IabHelper.IOnIabSetupFinishedListener
{
public IabResult Data { get; internal set; } = null;
public void OnIabSetupFinished(IabResult res)
{
if (res != null) { Data = res; }
}
}
and a calling method:
public class Class1
{
public void Method1()
{
FinishedListener listner = new FinishedListener();
SomeClass.Init(listner );
// Do something with "listner.Data.Response"
}
}
Because Init class works asynchronously, listner.Data will not be available at once.
What's the best way to implement waiting for this scenario?
I am not sure if your Init method is awaitable, assuming it is you can do something like this;
public async void Method1()
{
FinishedListener listner = new FinishedListener();
await SomeClass.Init(listner);
// Do something with "listner.Data.Response"
}
In case it is non-awaitable do this:
public async void Method1()
{
FinishedListener listner = new FinishedListener();
await Task.Run(()=>{ SomeClass.Init(listner); });
// Do something with "listner.Data.Response"
}
When this executes what will happen is that your existing compiler will wait for execution of await SomeClass.Init(listner); and then the next line shall execute.
I want to implement a class which runs a background task, looping and updating the state of the class. Once the class falls out of scope, running the background task has no value, so I would like to exit the loop and allow the task to complete and release the thread.
public class ValueProvider
{
private ConfigurationReloadToken _reloadToken = new ConfigurationReloadToken();
public string Value {get; private set;}
public IChangeToken ChangeToken => _reloadToken;
public void Load()
{
// Load the initial value.
Value = "Foo";
// Watch for changes to and reload the value.
WatchForChanges();
}
private void WatchForChanges() => Task.Run(WatchAsync);
private async Task WatchAsync()
{
var stillInScope = true;
while(stillInScope)
{
// Watch for new values.
Value = await LoadNewValueAsync();
// Signal a change.
OnReload();
}
}
private async Task<string> LoadNewValueAsync()
{
// Simulate an actual lookup which blocks until a new value is available.
await Task.Delay(TimeSpan.FromSeconds(30));
return "Bar";
}
private void OnReload()
{
var previousToken = Interlocked.Exchange(
ref _reloadToken,
new ConfigurationReloadToken());
previousToken.OnReload();
}
}
Since the created Task has a reference to the ValueProvider, the instance will never fall out of scope. The solution probably has to include accessing the ValueProvider from the background task via a WeakReference<T> to allow it to go out of scope, but I'm open to solutions.
How can I detect that the "foreground" object has fallen out of scope and stop the accompanied background task?
I'm wrapping a library for my own use. To get a certain property I need to wait for an event. I'm trying to wrap that into an async call.
Basically, I want to turn
void Prepare()
{
foo = new Foo();
foo.Initialized += OnFooInit;
foo.Start();
}
string Bar
{
return foo.Bar; // Only available after OnFooInit has been called.
}
Into this
async string GetBarAsync()
{
foo = new Foo();
foo.Initialized += OnFooInit;
foo.Start();
// Wait for OnFooInit to be called and run, but don't know how
return foo.Bar;
}
How could this best be accomplished? I could just loop and wait, but I'm trying to find a better way such as using Monitor.Pulse(), AutoResetEvent or something else.
Thats where TaskCompletionSource comes into play. There is little room for the new async keyword here. Example:
Task<string> GetBarAsync()
{
TaskCompletionSource<string> resultCompletionSource = new TaskCompletionSource<string>();
foo = new Foo();
foo.Initialized += OnFooInit;
foo.Initialized += delegate
{
resultCompletionSource.SetResult(foo.Bar);
};
foo.Start();
return resultCompletionSource.Task;
}
Sample use (with fancy async)
async void PrintBar()
{
// we can use await here since bar returns a Task of string
string bar = await GetBarAsync();
Console.WriteLine(bar);
}