C# - How to run multi await in one method? - c#

I don't know how to run multi await methods in single method. For example my code as below:
public static async Task<bool> Authenticate()
{
bool authen = false;
string message = String.Empty;
try
{
session = await FacebookSessionClient.LoginAsync("user_about_me,read_stream");
fbAccessToken = session.AccessToken;
fbFacbookID = session.FacebookId;
await saveProfile(fbFacebookID); //error here,my app is closed at here
authen = true;
}
catch (InvalidOperationException e)
{
authen = false;
}
return authen;
}
And I have method save profile
public async static void saveProfile(string fbFacbookID)
{
string response = string.Empty;
if (!string.IsNullOrEmpty(fbFacbookID))
{
response=await StaticClass.getJsonStream(string.Format("http://graph.facebook.com/{0}", fbFacbookID));
JObject _object = JObject.Parse(response);
SaveValueSetting("usernameFB",(string)_object["username"]);
}
else
{
return;
}
}
But I cannot run method? So how do I fix it?

you can use below mentioned code.
private void Button_Click_1(object sender, RoutedEventArgs e)
{
MyMethod();
MyMethod1();
}
public async Task MyMethod()
{
Task<int> longRunningTask = LongRunningOperation();
//indeed you can do independent to the int result work here
//and now we call await on the task
int result = await longRunningTask;
//use the result
MessageBox.Show(result.ToString());
}
public async Task MyMethod1()
{
Task<int> longRunningTask = SecondMethod();
//indeed you can do independent to the int result work here
//and now we call await on the task
int result = await longRunningTask;
//use the result
MessageBox.Show(result.ToString());
}
public async Task<int> LongRunningOperation() // assume we return an int from this long running operation
{
await Task.Delay(5000); //5 seconds delay
return 1;
}
public async Task<int> SecondMethod()
{
await Task.Delay(2000);
return 1;
}

Related

Blazor field gets null

I have this code in blazor:
It's just a simple method to update the div each second:
<div style="font-size:50px">#dailyCases.ToString("0,0.00")</div>
#code
{
private double dailyCases;
private bool needsUpdate = false;
private CovidDataManager covidManager;
protected async override Task OnInitializedAsync()
{
Console.WriteLine("init");
dailyCases = await updateData();
await StartCounter();
}
private Task StartCounter()
{
var timer = new System.Timers.Timer(1000);
timer.Elapsed += async (sender, e) =>
{
dailyCases = await update();
await InvokeAsync(StateHasChanged);
};
timer.Start();
return Task.CompletedTask;
}
private async Task<double> updateData()
{
var httpResponse = await covidRepository.GetYesterdayData("FRANCE");
var covidDailyInfoDTO = mapper.Map<Covid19Portal.Shared.DTO.CovidDailyInfoDTO>(httpResponse.Response);
var covidManager = new Covid19Portal.Shared.CovidDataManager(covidDailyInfoDTO);
return await Task.FromResult(covidManager.SickUpToNow);
}
private async Task<double> update()
{
return await Task.FromResult(covidManager.SickUpToNow);
//return await Task.FromResult(covidManager.SickUpToNow);
}
}
I get and error that covidManager is null after update gets called.
Any idea why?

C# Pausing Async Task works in one method, but not another

I have a class called PauseOrCancelToken, created by another class, PauseOrCancelTokenSource. PauseOrCancelToken basically encapsulates both a CancellationToken and PauseToken implemented from this MSDN blog post: https://blogs.msdn.microsoft.com/pfxteam/2013/01/13/cooperatively-pausing-async-methods/
I have tested it, and in a simple example use case (MethodA in the code I am about to post), it works as intended.
However, when I test it with non-trivial code that I intend to use in production (MethodB/ProxyTester.Start()), it is not pausing the async task.
public partial class PauseCancelForm : Form
{
private PauseOrCancelTokenSource pcts = new PauseOrCancelTokenSource();
public PauseCancelForm()
{
InitializeComponent();
}
private void StartButton_Click(object sender, EventArgs e)
{
Task.Run(() =>
{
MethodA(pcts.Token).Wait();
});
}
private async Task MethodA(PauseOrCancelToken pct)
{
//Pauses as intended when the pause button is clicked.
for (int i = 0; i < 10000; i++)
{
Console.WriteLine(i);
await Task.Delay(1000);
await pct.PauseOrCancelIfRequested();
}
}
private async Task MethodB(PauseOrCancelToken pct)
{
//Doesn't pause.
var proxies = new List<Proxy>();
var judges = new List<ProxyJudge>();
for (int i = 0; i < 10000; i++)
{
proxies.Add(new Proxy("127.0.0." + RandomUtility.GetRandomInt(1, 100), 8888));
}
judges.Add(new ProxyJudge("http://azenv.net"));
await ProxyTester.Start(proxies, judges, pct);
}
private void PauseButton_Click(object sender, EventArgs e)
{
pcts.Pause();
}
private void StopButton_Click(object sender, EventArgs e)
{
pcts.Cancel();
}
private void ResumeButton_Click(object sender, EventArgs e)
{
pcts.Resume();
}
}
public class PauseOrCancelTokenSource
{
private PauseTokenSource pts = new PauseTokenSource();
private CancellationTokenSource cts = new CancellationTokenSource();
public PauseOrCancelToken Token { get { return new PauseOrCancelToken(pts, cts); } }
public void Pause()
{
pts.IsPaused = true;
}
public void Resume()
{
pts.IsPaused = false;
}
public void Cancel()
{
cts.Cancel();
}
}
public class PauseOrCancelToken
{
private PauseToken pt;
private CancellationToken ct;
public PauseOrCancelToken(PauseTokenSource pts, CancellationTokenSource cts)
{
this.pt = pts.Token;
this.ct = cts.Token;
}
public async Task PauseIfRequested()
{
await pt.WaitWhilePausedAsync();
}
public void CancelIfRequested()
{
ct.ThrowIfCancellationRequested();
}
public async Task PauseOrCancelIfRequested()
{
await PauseIfRequested();
CancelIfRequested();
}
}
public class ProxyTester
{
public async static Task Start(List<Proxy> proxies, List<ProxyJudge> judges, PauseOrCancelToken pct, List<ProxyTest> tests = null)
{
if (tests == null)
{
tests = new List<ProxyTest>();
}
//Get external IP to check if proxy is anonymous.
var publicIp = await WebUtility.GetPublicIP();
//Validate proxy judges.
var tasks = new List<Task>();
foreach (var judge in judges)
{
tasks.Add(Task.Run(async () => {
judge.IsValid = await judge.TestValidityAsync();
await pct.PauseOrCancelIfRequested();
}));
}
await Task.WhenAll(tasks);
var validJudges = from judge in judges
where judge.IsValid
select judge;
if (validJudges.Count() == 0)
{
throw new Exception("No valid judges loaded.");
}
//Validate proxy tests.
tasks.Clear();
foreach (var test in tests)
{
tasks.Add(Task.Run(async () => {
test.IsValid = await test.TestValidityAsync();
await pct.PauseOrCancelIfRequested();
}));
}
await Task.WhenAll(tasks);
var validTests = from test in tests
where test.IsValid
select test;
var count = 0;
//Test proxies with a random, valid proxy judge. If valid, test with all valid proxy tests.
tasks.Clear();
foreach (var proxy in proxies)
{
tasks.Add(Task.Run(async () =>
{
proxy.IsValid = await proxy.TestValidityAsync(validJudges.ElementAt(RandomUtility.GetRandomInt(0, validJudges.Count())));
count++;
Console.WriteLine(count);
await pct.PauseOrCancelIfRequested();
if (proxy.IsValid)
{
proxy.TestedSites.AddRange(validTests);
var childTasks = new List<Task>();
foreach (var test in validTests)
{
childTasks.Add(Task.Run(async () =>
{
proxy.TestedSites.ElementAt(proxy.TestedSites.IndexOf(test)).IsValid = await proxy.TestValidityAsync(test);
await pct.PauseOrCancelIfRequested();
}));
}
await Task.WhenAll(childTasks);
}
}));
}
await Task.WhenAll(tasks);
}
}
In general, code in ProxyTester.Start uses pause token this way:
foreach (var judge in judges)
{
tasks.Add(Task.Run(async () => {
judge.IsValid = await judge.TestValidityAsync();
await pct.PauseOrCancelIfRequested();
}));
}
This runs judges.Length number of tasks. What happens when you pause token? Well, nothing useful actually. All tasks continue to run, and all of them will complete their useful work (await judge.TestValidityAsync()). Then, when all useful work is done, and they should just complete - they will pause on await pct.PauseOrCancelIfRequested(). I doubt that is the result you desire. Changing the order won't help much.
Compare that to "working" example:
for (int i = 0; i < 10000; i++)
{
Console.WriteLine(i);
await Task.Delay(1000);
await pct.PauseOrCancelIfRequested();
}
Here execution is sequential (and not parallel like above) and you check pause token every iteration, so it works as expected.
If you want to be able to pause in your real world scenario - don't start all those tasks at once, run them in batches (with SemaphoreSlim or similar technique), and check pause token after each batch.

Refactor to remove Taks.Run from my code

I just wrote the following code
public void Save()
{
while (this.IsAsyncInProcess)
Thread.Sleep(100);
this.customer.OrderCount = this.orders.Count();
this.customer.OrderTotal = this.orders.Sum(o => x.Total);
this.customerRepo.Save();
}
public async Task LoadAsync()
{
this.IsAsyncInProcess = true;
this.customer = await this.customerRepo.GetCustomerAsync(...);
this.orders = await this.customerRepo.GetOrdersAsync(...);
this.IsAsyncInProcess = false;
}
Now I had a classical deadlock because, after this.orders completed, it would wait for the gui thread to resume in order to set this.IsAsyncInProcess to false. However, the gui thread was busy inside Save()
Now I refactored LoadAsync to
public async Task LoadAsync()
{
await Task.Run(async () =>
{
this.IsAsyncInProcess = true;
this.customer = await this.customerRepo.GetCustomerAsync(...);
this.orders = await this.customerRepo.GetOrdersAsync(...);
this.IsAsyncInProcess = false;
});
}
I can't just refactor Save to SaveAsync for compability reasons.
Is there a better way to achive this, without using Task.Run?
You can use async locking. If you can't change the signiture of Save then you can just proxy to an async local function.
static SemaphoreSlim sem = new SemaphoreSlim(1,1);
public void Save()
{
SaveAsync();
public async Task SaveAsync()
{
await sem.WaitAsync();
try{
this.customer.OrderCount = this.orders.Count();
this.customer.OrderTotal = this.orders.Sum(o => x.Total);
this.customerRepo.Save();
}finally{
sem.Release();
}
}
}
public async Task LoadAsync()
{
await sem.WaitAsync();
try{
this.customer = await this.customerRepo.GetCustomerAsync(...);
this.orders = await this.customerRepo.GetOrdersAsync(...);
}finally{
sem.Release();
}
}
or even better create your own async lock
static SemaphoreSlim sem = new SemaphoreSlim(1,1);
public static async Task<IDisposable> LockAsync(){
await sem.WaitAsync();
return Disposable.Create(()=>sem.Release());
}
public void Save()
{
SaveAsync();
public async Task SaveAsync()
{
using(await LockAsync()){
this.customer.OrderCount = this.orders.Count();
this.customer.OrderTotal = this.orders.Sum(o => x.Total);
this.customerRepo.Save();
}
}
}
public async Task LoadAsync()
{
using(await LockAsync()){
this.customer = await this.customerRepo.GetCustomerAsync(...);
this.orders = await this.customerRepo.GetOrdersAsync(...);
}
}

How to refactor this C# code

I have these functions
public async Task<List<Machine>> GetMachines()
{
await Initialize();
await SyncMachines();
return await machineTable.ToListAsync();
}
public async Task InsertMachines(List<Machine> machines)
{
await Initialize();
await Task.WhenAll(machines.Select(m => machineTable.InsertAsync(m)));
await SyncMachines();
}
I am writing a parent class to put these functions in, such that the functions getMachines() and InsertMachines() become getObject and InsertObject where the List<Machine> can be a list of any objects, so they can return and accept any type of list
How do I declare functions like this?
According to your description, I created my azure sync table class as follows, you could refer to it:
public class AzureCloudSyncTable<TModel> where TModel : class
{
public static MobileServiceClient MobileService = new MobileServiceClient(
"https://{your-mobile-app-name}.azurewebsites.net"
);
private IMobileServiceSyncTable<TModel> syncTable = MobileService.GetSyncTable<TModel>();
#region Offline sync
private async Task InitLocalStoreAsync()
{
if (!MobileService.SyncContext.IsInitialized)
{
var store = new MobileServiceSQLiteStore("localstore.db");
store.DefineTable<TModel>();
await MobileService.SyncContext.InitializeAsync(store);
}
await SyncAsync();
}
private async Task SyncAsync()
{
await PushAsync();
await syncTable.PullAsync(typeof(TModel).Name, syncTable.CreateQuery());
}
private async Task PushAsync()
{
try
{
await MobileService.SyncContext.PushAsync();
}
catch (MobileServicePushFailedException ex)
{
if (ex.PushResult != null)
{
foreach (var error in ex.PushResult.Errors)
{
await ResolveConflictAsync(error);
}
}
}
}
private async Task ResolveConflictAsync(MobileServiceTableOperationError error)
{
//var serverItem = error.Result.ToObject<TModel>();
//var localItem = error.Item.ToObject<TModel>();
//// Note that you need to implement the public override Equals(TModel item)
//// method in the Model for this to work
//if (serverItem.Equals(localItem))
//{
// // Items are the same, so ignore the conflict
// await error.CancelAndDiscardItemAsync();
// return;
//}
//// Client Always Wins
//localItem.Version = serverItem.Version;
//await error.UpdateOperationAsync(JObject.FromObject(localItem));
// Server Always Wins
//await error.CancelAndDiscardItemAsync();
}
#endregion
#region public methods
public async Task<List<TModel>> GetAll()
{
await InitLocalStoreAsync();
await SyncAsync();
return await syncTable.ToListAsync();
}
public async Task Insert(List<TModel> items)
{
await InitLocalStoreAsync();
await Task.WhenAll(items.Select(item => syncTable.InsertAsync(item)));
await PushAsync();
}
#endregion
}
Additionally, for more details about Handling Conflict Resolution, you could refer to adrian hall's book here.

How to return a result from an async task?

I would like to return a string result from an async task.
System.Threading.Tasks.Task.Run(async () => await audatex.UploadInvoice(assessment, fileName));
public async Task UploadInvoice(string assessment, string fileName)
{
//Do stuff
return string;
}
Async programming confuses me, can someone please explain it?
Async programming can take a while to get your head around, so I'll post what has been useful for me in case it helps anyone else.
If you want to separate the business logic from the async code, you can keep your UploadInvoice method async-free:
private string UploadInvoice(string assessment, string filename)
{
// Do stuff
Thread.Sleep(5000);
return "55";
}
Then you can create an async wrapper:
private async Task<string> UploadInvoiceAsync(string assessment, string filename)
{
return await Task.Run(() => UploadInvoice(assessment, filename));
}
Giving you the choice of which to call:
public async Task CallFromAsync()
{
string blockingInvoiceId = UploadInvoice("assessment1", "filename");
string asyncInvoiceId = await UploadInvoiceAsync("assessment1", "filename");
}
Sometimes you might need to call an async method from a non-async method.
// Call the async method from a non-async method
public void CallFromNonAsync()
{
string blockingInvoiceId = UploadInvoice("assessment1", "filename");
Task<string> task = UploadInvoiceAsync("assessment1", "filename");
string invoiceIdAsync = task.GetAwaiter().GetResult();
}
----EDIT: Adding more examples because people have found this useful----
Sometimes you want to wait on a task, or continue a task with a method on completion. Here's a working example you can run in a console application.
class Program
{
static void Main(string[] args)
{
var program = new Program();
program.Run();
Console.ReadKey();
}
async void Run()
{
// Example 1
Console.WriteLine("#1: Upload invoice synchronously");
var receipt = UploadInvoice("1");
Console.WriteLine("Upload #1 Completed!");
Console.WriteLine();
// Example 2
Console.WriteLine("#2: Upload invoice asynchronously, do stuff while you wait");
var upload = UploadInvoiceAsync("2");
while (!upload.IsCompleted)
{
// Do stuff while you wait
Console.WriteLine("...waiting");
Thread.Sleep(900);
}
Console.WriteLine("Upload #2 Completed!");
Console.WriteLine();
// Example 3
Console.WriteLine("#3: Wait on async upload");
await UploadInvoiceAsync("3");
Console.WriteLine("Upload #3 Completed!");
Console.WriteLine();
// Example 4
var upload4 = UploadInvoiceAsync("4").ContinueWith<string>(AfterUploadInvoice);
}
string AfterUploadInvoice(Task<string> input)
{
Console.WriteLine(string.Format("Invoice receipt {0} handled.", input.Result));
return input.Result;
}
string UploadInvoice(string id)
{
Console.WriteLine(string.Format("Uploading invoice {0}...", id));
Thread.Sleep(2000);
Console.WriteLine(string.Format("Invoice {0} Uploaded!", id));
return string.Format("<{0}:RECEIPT>", id); ;
}
Task<string> UploadInvoiceAsync(string id)
{
return Task.Run(() => UploadInvoice(id));
}
}
Your method should return Task<string> , not Task:
public async Task<string> UploadInvoice(string assessment, string fileName)
{
//Do stuff
return string;
}
public async Task<string> UploadInvoice(string assessment, string fileName)
{
string result = GetResultString();//Do stuff
return Task.FromResult(result);
}
Do this:
public async Task<string> UploadInvoice(string assessment, string fileName)
Then await the result:
string result = await UploadInvoice("", "");
More examples can be seen here:
Async Return Types

Categories