I am trying to make a method of mine into something that can be called asynchronously.
Normally from the AddQueue Method, I would just call the ListOfJobsInQueue methods in the WorkingSession class, get its result and be done with it.
Using what info I could find regarding Async programming on here, I have done up the below code, but it seems to be getting stuck on the CurrentPageCode property call.
It does not even get to the MessageBox.Show("Processing complete with " + queueResult.Count + " rows"); line.
Could someone please assist and show me where I'm going wrong?
//Primary Class
public void AddQueue()
{
MessageBox.Show(GetJobsFromQueueAsync().Result.Count().ToString());
}
async Task<List<string>> GetJobsFromQueueAsync()
{
Task<List<string>> getJobsTask = WorkingSession.GetlistOfJobsAsync();
List<string> queueResult = await getJobsTask;
MessageBox.Show("Processing complete with " + queueResult.Count + " rows");
return queueResult;
}
//***
//WorkingSession Class
public Task<List<string>> GetlistOfJobsAsync()
{
return Task.Run<List<string>>(() =>
{
return ListOfJobsInQueue();
});
}
public List<string> ListOfJobsInQueue()
{
if (CurrentPageCode == "CS1")
{
List<string> actionList = new List<string>();
short pageNum = PageCurrent;
short pageMax = PageMax;
for (short atPage = pageNum; atPage <= pageMax; atPage++)
{
//Scan each job on the current queue page
for (int lineNum = 5; lineNum < 18; lineNum++)
{
string reference = GetJobText(new Coordinate { row = lineNum });
actionList.Add(reference);
}
//Once finished with this job page, goto the next
SendCMDKey(Mnemonic.F8);
}
return actionList;
}
else
{
return null;
}
}
//Other method / property signatures (for reference)
public string CurrentPageCode;
public bool SendCMDKey(Mnemonic command)
public string GetJobText(Coordinate coordinate)
//***
The deadlock problem is actually this method:
public void AddQueue()
{
MessageBox.Show(GetJobsFromQueueAsync().Result.Count().ToString());
}
Calling Task.Wait or Task<T>.Result should be avoided in async code. I explain the deadlock in full on my blog, but the summary version is that await will capture a context (in this case, the UI context) and attempt to resume its async method on that context (in this case, on the UI thread). With some contexts (e.g., the UI context), if you block a thread in that context (e.g., calling Task<T>.Result on the UI thread), then the async method cannot resume on that context, causing a deadlock.
To fix it, use async all the way:
public async Task AddQueueAsync()
{
var jobs = await GetJobsFromQueueAsync();
MessageBox.Show(jobs.Count().ToString());
}
This code is also not ideal, though in a much more subtle way:
public Task<List<string>> GetlistOfJobsAsync()
{
return Task.Run<List<string>>(() =>
{
return ListOfJobsInQueue();
});
}
By wrapping an entire method's logic in Task.Run, what you're really doing is writing a "fake asynchronous" method. It's got an asynchronous signature but the logic is just synchronous work on a background thread.
It's best to push any Task.Run use as far towards the UI layer as possible; keep it out of any reusable library methods. Make your APIs tell the truth: have synchronous signatures for synchronous work. I have a blog series that goes into detail.
The simplest that I can
public async Task<int> GetWorkFlowStageAsync(string tracker,CancellationToken? token = null)
{
return await Task.FromResult(0);
}
Related
I've written a class that asynchronously pings a subnet. It works, however, the number of hosts returned will sometimes change between runs. Some questions:
Am I doing something wrong in the code below?
What can I do to make it work better?
The ScanIPAddressesAsync() method is called like this:
NetworkDiscovery nd = new NetworkDiscovery("192.168.50.");
nd.RaiseIPScanCompleteEvent += HandleScanComplete;
nd.ScanIPAddressesAsync();
namespace BPSTestTool
{
public class IPScanCompleteEvent : EventArgs
{
public List<String> IPList { get; set; }
public IPScanCompleteEvent(List<String> _list)
{
IPList = _list;
}
}
public class NetworkDiscovery
{
private static object m_lockObj = new object();
private List<String> m_ipsFound = new List<string>();
private String m_ipBase = null;
public List<String> IPList
{
get { return m_ipsFound; }
}
public EventHandler<IPScanCompleteEvent> RaiseIPScanCompleteEvent;
public NetworkDiscovery(string ipBase)
{
this.m_ipBase = ipBase;
}
public async void ScanIPAddressesAsync()
{
var tasks = new List<Task>();
m_ipsFound.Clear();
await Task.Run(() => AsyncScan());
return;
}
private async void AsyncScan()
{
List<Task> tasks = new List<Task>();
for (int i = 2; i < 255; i++)
{
String ip = m_ipBase + i.ToString();
if (m_ipsFound.Contains(ip) == false)
{
for (int x = 0; x < 2; x++)
{
Ping p = new Ping();
var task = HandlePingReplyAsync(p, ip);
tasks.Add(task);
}
}
}
await Task.WhenAll(tasks).ContinueWith(t =>
{
OnRaiseIPScanCompleteEvent(new IPScanCompleteEvent(m_ipsFound));
});
}
protected virtual void OnRaiseIPScanCompleteEvent(IPScanCompleteEvent args)
{
RaiseIPScanCompleteEvent?.Invoke(this, args);
}
private async Task HandlePingReplyAsync(Ping ping, String ip)
{
PingReply reply = await ping.SendPingAsync(ip, 1500);
if ( reply != null && reply.Status == System.Net.NetworkInformation.IPStatus.Success)
{
lock (m_lockObj)
{
if (m_ipsFound.Contains(ip) == false)
{
m_ipsFound.Add(ip);
}
}
}
}
}
}
One problem I see is async void. The only reason async void is even allowed is only for event handlers. If it's not an event handler, it's a red flag.
Asynchronous methods always start running synchronously until the first await that acts on an incomplete Task. In your code, that is at await Task.WhenAll(tasks). At that point, AsyncScan returns - before all the tasks have completed. Usually, it would return a Task that will let you know when it's done, but since the method signature is void, it cannot.
So now look at this:
await Task.Run(() => AsyncScan());
When AsyncScan() returns, then the Task returned from Task.Run completes and your code moves on, before all of the pings have finished.
So when you report your results, the number of results will be random, depending on how many happened to finish before you displayed the results.
If you want make sure that all of the pings are done before continuing, then change AsyncScan() to return a Task:
private async Task AsyncScan()
And change the Task.Run to await it:
await Task.Run(async () => await AsyncScan());
However, you could also just get rid of the Task.Run and just have this:
await AsyncScan();
Task.Run runs the code in a separate thread. The only reason to do that is in a UI app where you want to move CPU-heavy computations off of the UI thread. When you're just doing network requests like this, that's not necessary.
On top of that, you're also using async void here:
public async void ScanIPAddressesAsync()
Which means that wherever you call ScanIPAddressesAsync() is unable to wait until everything is done. Change that to async Task and await it too.
This code needs a lot of refactoring and bugs like this in concurrency are hard to pinpoint. My bet is on await Task.Run(() => AsyncScan()); which is wrong because AsyncScan() is async and Task.Run(...) will return before it is complete.
My second guess is m_ipsFound which is called a shared state. This means there might be many threads simultaneously reading and writing on this. List<T> is not a data type for this.
Also as a side point having a return in the last line of a method is not adding to the readability and async void is a prohibited practice. Always use async Task even if you return nothing. You can read more on this very good answer.
I have this code to retrieve data from my database:
public async Task<IEnumerable<Member>> GetAllMembersAsync()
{
var members = Repository.GetAll<Member>();
return await Task.Run(() => members.ToListAsync());
}
For an unknown reason (maybe a bug?), I have to use Task.Run in order to make this work (the repository just returns a DbSet<Member>. If I don't do this, my UI hangs forever.
The problem is that I can't do 2 database operations at the same time this way. If I do this, I get this error:
A second operation started on this context before a previous asynchronous operation completed. Use 'await' to ensure that any asynchronous operations have completed before calling another method on this context. Any instance members are not guaranteed to be thread safe.
As you see, I'm already using await.
Is there any way to solve this so I can actually do 2 database operations at the same time and so they run in order?
EDIT:
Code that calls this:
private async void LoadMembers()
{
try
{
var members = await MemberService.GetAllMembersAsync();
Members = new ObservableCollection<Member>(members);
}
catch (EntityException)
{
// connection lost?
}
}
The answer is no. As the error suggests you can't have 2 concurrent EF operations at the same time. Here's a more thorough answer about that: Does Entity Framework support parallel async queries?
On top of that, you don't need to use Task.Run to solve what seems to be a deadlock issue. Simply use ConfigureAwait to make sure the async operation doesn't need the UI SynchronizationContext to complete on. (also, make sure you don't block on async code with Task.Wait or Task.Result):
public async Task<IEnumerable<Member>> GetAllMembersAsync()
{
return await Repository.GetAll<Member>().ToListAsync().ConfigureAwait(false);
}
private async void LoadMembers()
{
try
{
var members = await MemberService.GetAllMembersAsync();
Members = new ObservableCollection<Member>(members);
}
catch (EntityException)
{
// connection lost?
}
}
I think you are in a deadlock situation because you are not using configureawait(true) properly.
You can do
public async Task<IEnumerable<Member>> GetAllMembersAsync()
{
var members = Repository.GetAll<Member>();
return await Task.Run(() => members.ToListAsync());
}
private async void LoadMembers()
{
try
{
var members = await MemberService.GetAllMembersAsync().ConfigureAwait(true);
Members = new ObservableCollection<Member>(members);
}
catch (EntityException)
{
// connection lost?
}
}
after the operation is complete, and if executed from the GUI thread, the GUI thread will resume.
I'm getting started on async/await using. I've written simple application using WPF based on MVVM pattern, but it doesn't work as I expected. The program works as there were no asynchronous functions: after executing execute function it freezes and unfreezes only after loop function ended.
Please tell me what part did I get wrong. I'd appreciate any feedback. :)
Here is my modelview class. It inherits from wpf class, that contains definitions of standard wpf functions like OnPropertyChanged.
public class ModelView : wpf
{
string _state;
public string state { get { return _state; } set { _state = value; OnPropertyChanged("state"); } }
public DelegateCommand work { get; set; }
public ModelView()
{
state = "Program started";
work=new DelegateCommand(_work);
}
async void _work(object parameter)
{
state = "Working...";
int j=await loop();
state = "Done: " + j;
}
async Task<int> loop()
{
int i;
for(i=0;i<1000000000;i++);
return i;
}
}
There isn't an asynchronous part in your code. Simply using the async keyword doesn't make it so. Use Task.Run instead if you wish to offload synchronous code to a different thread:
async void _work(object parameter)
{
status = "Working...";
int j=await Task.Run(() => loop());
status = "Done: " + j;
}
int loop()
{
int i;
for(i=0;i<1000000000;i++);
return i;
}
If you actually have an asynchronous operation, you can use that instead:
async void _work(object parameter)
{
status = "Working...";
await Task.Delay(1000);
status = "Done: " + j;
}
Guideline: If your "async" method doesn't have an await inside it, it isn't asynchronous.
You aren't doing anything async. The async keyword does not mean "creates another thread"; it is quite complex, but basically it allows code to work with continuations when another asynchronous operation completes. Good examples would include asynchronous database access, file access, network access, etc. It can also include asynchronous long-running operations via threads and Task.Run. But: you aren't doing that. There is nothing incomplete to await - the code just runs on the main thread. It only schedules a continuation when there is something incomplete to continue from.
To quote the compiler (talking about the loop method):
Warning This async method lacks 'await' operators and will run synchronously. Consider using the 'await' operator to await non-blocking API calls, or 'await Task.Run(...)' to do CPU-bound work on a background thread.
It looks like the problem is your loop function. Even though you have declared it as async there are no await statements in it and you should get a compiler warning as #Marc Gravell pointed out.
The function spins through large number of loop iterations hogging the UI thread which will cause the blocking, it then returns the final value.
So your loop function is in fact a synchronous function. Assuming you were doing this for test purposes a good way to simulate an async operation is to use Task.Delay.
For example:
async Task<int> loop()
{
await Task.Delay(5000);
return 1;
}
I am new the using Task.Run() along with async and await to make UI more responsive, so likely I have not implemented something correctly.
I have reviewed the great articles from Stephen Cleary about using AsyncCommands and have used his code from Patterns for Asynchronous MVVM Applications: Commands as a basis for having a responsive UI but when I run the code it still seems to freeze up (I am not able to move the window or interact with other buttons until the function has fully finished.
I am trying to perform a search which usually takes 5-10 seconds to return. Below is the code that creates the AsyncCommand along with the what the function does.
Code:
public ICommand SearchCommand
{
get
{
if (_SearchCommand == null)
{
_SearchCommand = AsyncCommand.Create(() => Search());
}
return _SearchCommand;
}
}
private async Task Search()
{
IEnumerable<PIPoint> points = await SearchAsync(_CurrentPIServer, NameSearch, PointSourceSearch).ConfigureAwait(false);
SearchResults.Clear();
foreach (PIPoint point in points)
{
SearchResults.Add(point.Name);
}
}
private async Task<IEnumerable<PIPoint>> SearchAsync(string Server, string NameSearch, string PointSourceSearch)
{
{
PIServers KnownServers = new PIServers();
PIServer server = KnownServers[Server];
server.Connect();
return await Task.Run<IEnumerable<PIPoint>>(()=>PIPoint.FindPIPoints(server, NameSearch, PointSourceSearch)).ConfigureAwait(false);
}
}
I am thinking that the issue is somewhere in how I am pushing the long running function onto a thread and its not getting off of the UI thread or my understanding of how Tasks and async/await are completely off.
EDIT 1:
Following Stephen's answer I updated the functions, but I am not seeing any change in the UI responsiveness. I created a second command that performs the same actions and I get the same response from UI in either case. The code now looks like the following
CODE:
public ICommand SearchCommand
{
get
{
if (_SearchCommand == null)
{
_SearchCommand = AsyncCommand.Create(async () =>
{
var results = await Task.Run(()=>Search(_CurrentPIServer, NameSearch, PointSourceSearch));
SearchResults = new ObservableCollection<string>(results.Select(x => x.Name));
});
}
return _SearchCommand;
}
}
public ICommand SearchCommand2
{
get
{
if (_SearchCommand2 == null)
{
_SearchCommand2 = new RelayCommand(() =>
{
var results = Search(_CurrentPIServer, NameSearch, PointSourceSearch);
SearchResults = new ObservableCollection<string>(results.Select(x => x.Name));
}
,()=> true);
}
return _SearchCommand2;
}
}
private IEnumerable<PIPoint> Search(string Server, string NameSearch, string PointSourceSearch)
{
PIServers KnownServers = new PIServers();
PIServer server = KnownServers[Server];
server.Connect();
return PIPoint.FindPIPoints(server, NameSearch, PointSourceSearch);
}
I must be missing something but I am not sure what at this point.
EDIT 2:
After more investigation on what was taking so long it turns out the iterating of the list after the results are found is what was hanging the process. By simply changing what the Search function was returning and having it already iterated over the list of objects allows for the UI to remain responsive. I marked Stephen's answer as correct as it handled my main problem of properly moving work off of the UI thread I just didnt move the actual time consuming work off.
My first guess is that the work queued to Task.Run is quite fast, and the delay is caused by other code (e.g., PIServer.Connect).
Another thing of note is that you are using ConfigureAwait(false) in Search which updates SearchResults - which I suspect is wrong. If SearchResults is bound to the UI, then you should be in the UI context when updating it, so ConfigureAwait(false) should not be used.
That said, there's a Task.Run principle that's good to keep in mind: push Task.Run as far up your call stack as possible. I explain this in more detail on my blog. The general idea is that Task.Run should be used to invoke synchronous methods; it shouldn't be used in the implementation of an asynchronous method (at least, not one that is intended to be reused).
As a final note, async is functional in nature. So it's more natural to return results than update collections as a side effect.
Combining these recommendations, the resulting code would look like:
private IEnumerable<PIPoint> Search(string Server, string NameSearch, string PointSourceSearch)
{
PIServers KnownServers = new PIServers();
PIServer server = KnownServers[Server];
// TODO: If "Connect" or "FindPIPoints" are naturally asynchronous,
// then this method should be converted back to an asynchronous method.
server.Connect();
return PIPoint.FindPIPoints(server, NameSearch, PointSourceSearch);
}
public ICommand SearchCommand
{
get
{
if (_SearchCommand == null)
{
_SearchCommand = AsyncCommand.Create(async () =>
{
var results = await Task.Run(() =>
Search(_CurrentPIServer, NameSearch, PointSourceSearch));
SearchResults = new ObservableCollection<string>(
results.Select(x => x.Name));
});
}
return _SearchCommand;
}
}
There are some things about the Async-await that just mystify me and I was wondering if anyone could explain something to me:
Just to note, my inquiries come after reading this: http://blogs.msdn.com/b/ericlippert/archive/2010/10/29/asynchronous-programming-in-c-5-0-part-two-whence-await.aspx
So Eric Lippert says
The “async” modifier on the method does not mean “this method is automatically scheduled to run on a worker thread asynchronously”
Why is it that we need to place Async on methods we want to run asynchronously? i.e.
private async Task<int> GetMeInt()
{
return 0;
}
private async void stuff()
{
var num = GetMeInt();
DoStuff();
int end = await num;
for (int i = 0; i < end; i++)
Console.WriteLine("blahblahblah");
}
The thing is that we don't want GetMeInt to actually do anything asynchronous internally. We just want it to run Synchronously, but we want it to run asynchronously as a whole when called by another method. It seems more sensible to me to put the async only on the Stuff() method and allow the GetMeInt() to run on another thread and return later.
Essentially I believe it would be something like such :
private int GetMeInt()
{
return 0;
}
private async void stuff()
{
int? num = null;
Thread t = new Thread(() => num = GetMeInt());
t.Start();
DoStuff();
t.Join();
for (int i = 0; i < (num??0); i++)
Console.WriteLine("blahblahblah");
}
After all, isn't the state machine only created on the Stuff() method? What makes it more confusing is the fact that the compiler gives a warning if I do put async in GetMeInt, its not really nice to be forced to wrap whatever is returned by GetMeInt() in the task object and this type of thing prevents us from using methods someone else wrote asynchronously.
Why didn't they design it in such a way so you could do something like this (This is the territory of untested theoretical code!). I'd imagine that there are reasons that have to do with the framework but I'd think that this sort of thing would be more intuitive. Am I missing something obvious about this async business? Am I suppose to just ignore the warning and go ahead, my OCD just won't let this go.
private async void stuff()
{
var s = Example.Run<int>(Delegate.CreateDelegate(typeof(Delegate), this, "GetMeInt"));
DoStuff();
for (int i = 0; i < s.Result; i++)
Console.WriteLine("blahblahblah");
}
public class Example
{
Thread t;
Object r;
private Example(){}
public static Example<T> Run<T>(Delegate pFunc)
{
Example<T> output = new Example<T>();
output.t = new Thread(() => output.r = (T)pFunc.DynamicInvoke());
output.t.Start();
return output;
}
public sealed class Example<T> : Example
{
public T Result
{
get
{
t.Join();
return (T)r;
}
private set;
}
}
}
I really don't understand, any explanation about this stuff would be appreciated.
All the async modifier means is that that this method is able to await things.
As the compiler is warning you, it is completely useless unless you actually have something to await.
You're actually asking how to do work on a background thread, then asynchronously wait for it to finish.
You can use Task.Run() to run code in the background, then await the resulting task.
The key thing to understand about async is that, strictly speaking, the method returns before its work has completed. That's essentially the only thing the keyword denotes. Your example that returns 0 right away does not do this "offloading" and so the compiler is warning you that there's no point in it being async.
That's why async methods should return a Task<T> (so you can determine when the method's work has actually completed and take action on the now-available result), and that's why anything that uses await has to itself be async (because now that outer method will also return before it is "done").