How to make async task not stall on response [duplicate] - c#

static async void SendTweetWithSinglePicture(string message, string image)
{
var auth = new SingleUserAuthorizer
{
CredentialStore = new SingleUserInMemoryCredentialStore
{
ConsumerKey = "",
ConsumerSecret = "",
AccessToken = "",
AccessTokenSecret = ""
}
};
var context = new TwitterContext(auth);
var uploadedMedia = await context.UploadMediaAsync(File.ReadAllBytes(#image));
var mediaIds = new List<ulong> { uploadedMedia.MediaID };
await context.TweetAsync(
message,
mediaIds
);
}
protected void Page_Load(object sender, EventArgs e)
{
SendTweetWithSinglePicture("test", "path");
}
How can I call a async method on Page_Load?

The question is if you want to make the Page_Load method async or not. If so:
protected async void Page_Load(object sender, EventArgs e)
{
await SendTweetWithSinglePicture("test", "path");
}
Or if you don't want it to be async:
protected void Page_Load(object sender, EventArgs e)
{
SendTweetWithSinglePicture("test", "path").Wait();
}
This does require your async method to return Task as it always should! (except event handlers)
The problem with this might be that the method doesn't complete before rendering the page. If it has to, you'd better make the method synchronous, or register the task using Page.RegisterAsyncTask and Page.ExecuteRegisteredAsyncTasks. Effectively this will freeze the Page_Load method too.
protected void Page_Load(object sender, EventArgs e)
{
PageAsyncTask t = new PageAsyncTask(SendTweetWithSinglePicture("test", "path"));
// Register the asynchronous task.
Page.RegisterAsyncTask(t);
// Execute the register asynchronous task.
Page.ExecuteRegisteredAsyncTasks();
}

You should use PageAsyncTask. It has samples in MSDN page.
// Register the asynchronous task.
Page.RegisterAsyncTask(new PageAsyncTask(SendTweetWithSinglePicture(message, image));
// Execute the register asynchronous task.
Page.ExecuteRegisteredAsyncTasks();
as I pointed the sample and explanations on MSDN page is pretty good.

Try This :
public void Page_Load(object sender, EventArgs e)
{
RegisterAsyncTask(new PageAsyncTask(LoadSomeData));
}
public async Task LoadSomeData()
{
var clientcontacts = Client.DownloadStringTaskAsync("api/contacts");
var clienttemperature = Client.DownloadStringTaskAsync("api/temperature");
var clientlocation = Client.DownloadStringTaskAsync("api/location");
await Task.WhenAll(clientcontacts, clienttemperature, clientlocation);
var contacts = Newtonsoft.Json.JsonConvert.DeserializeObject<List<Contact>>(await clientcontacts);
var location = Newtonsoft.Json.JsonConvert.DeserializeObject<string>(await clientlocation);
var temperature = Newtonsoft.Json.JsonConvert.DeserializeObject<string>(await clienttemperature);
listcontacts.DataSource = contacts;
listcontacts.DataBind();
Temparature.Text = temperature;
Location.Text = location;
}

Related

Cannot implicitly convert type 'string' to 'System.Threading.Tasks.Task<string>' in c#

I have this code
private void button1_Click(object sender, EventArgs e)
{
//===========> Getting error here <==================//
textBox2.Text = CallFunc(textBox1.Text);
}
static async Task<string> CallFunc(string str)
{
Program p = new Program();
string s = await p.DocumentToText(str);
return s;
}
public async Task<string> DocumentToText(string path)
{
string txt = String.Empty;
AmazonTextractClient client = new AmazonTextractClient(key, Skey, reg);
//some AWS functionality
Thread.Sleep(2000);
txt = "hello world";
return txt;
}
I changed this button1_Click function to
private void button1_Click(object sender, EventArgs e)
{
var d = await CallFunc(textBox1.Text);
textBox2.Text = d.Results();
}
as was recommended by one answers of this question
Cannot implicitly convert type 'string' to 'System.Threading.Tasks.Task<string>'
but that still does not work
Add async in button1_Click event
private async void button1_Click(object sender, EventArgs e)
{
var d = await CallFunc(textBox1.Text);
textBox2.Text = d;
}
Use Async Task in button1_Click method
private async Task button1_Click(object sender, EventArgs e)
{
var d = await CallFunc(textBox1.Text);
textBox2.Text = d.Results();
}

"Cross-thread operation not valid" inside foreach [duplicate]

This question already has answers here:
Cross-thread operation not valid: Control accessed from a thread other than the thread it was created on
(22 answers)
Closed 3 years ago.
I'm trying to load data to a combobox and it's working when i run the form without debugging. But when i try to run it with debug mode I get an error :System.InvalidOperationException: 'Cross-thread operation not valid: Control 'ResultBox' accessed from a thread other than the thread it was created on.'
How can I fix this? And btw a have a background worker that writes the message when the data is downloaded. I read somewhere that this issue can be fixed using backgroundworker. Here is the form code:
public Form1()
{
InitializeComponent();
backgroundWorker1.WorkerReportsProgress = true;
}
private void Form1_Load(object sender, EventArgs e)
{
backgroundWorker1.RunWorkerAsync();
}
private Task GetDataTask() {
return Task.Factory.StartNew(() => {
List<Result> results = new List<Result>();
results =
GetResults.GetData("http://worldcup.sfg.io/teams/results/");
foreach (var result in results)
{
ResultBox.Items.Add(result.Fifa_Code);
}
});
}
private void ResultBox_SelectedIndexChanged(object sender, EventArgs e)
{
}
private void SaveTeam_Click(object sender, EventArgs e)
{
}
private async void backgroundWorker1_DoWork(object sender,
DoWorkEventArgs e)
{
await GetDataTask();
}
private void backgroundWorker1_ProgressChanged(object sender,
ProgressChangedEventArgs e)
{
resultsLoadedLabel.Text = (e.ProgressPercentage.ToString() + "%");
}
private void backgroundWorker1_RunWorkerCompleted(object sender,
RunWorkerCompletedEventArgs e)
{
resultsLoadedLabel.Text = "Podaci učitani!";
}
This line of code inside foreach gets the exception :
ResultBox.Items.Add(result.Fifa_Code);
This is the class that gets results:
public class GetResults
{
public static List<Result> GetData(string url) {
var client = new RestClient();
var request = new RestRequest(url, Method.GET);
request.AddHeader("User-Agent", "Nothing");
IRestResponse<List<Result>> results = client.Execute<List<Result>>
(request);
return results.Data;
}
}
If going async, then go async all the way. RestSharp allows you to make async calls
So you can refactor data access to
public class GetResults {
public static async Task<List<Result>> GetDataAsync(string url) {
var client = new RestClient();
var request = new RestRequest(url, Method.GET);
request.AddHeader("User-Agent", "Nothing");
IRestResponse<List<Result>> results = await client.ExecuteTaskAsync<List<Result>>(request);
return results.Data;
}
}
Next, since the form load is an event handler, you can make that async as well and load the data.
public Form1() {
InitializeComponent();
}
private async void Form1_Load(object sender, EventArgs e) {
//On UI thread
resultsLoadedLabel.Text = "Loading data!";
//get data on separate thread (non blocking)
List<Result> results = await GetResults.GetDataAsync("http://worldcup.sfg.io/teams/results/");
//Back on UI thread
resultsLoadedLabel.Text = "Podaci učitani!";
foreach (var result in results) {
ResultBox.Items.Add(result.Fifa_Code);
}
}
Making sure when accessing UI controls while using async calls that they are accessed on the main thread that created them (see comments).

Call Async Method in Page_Load

static async void SendTweetWithSinglePicture(string message, string image)
{
var auth = new SingleUserAuthorizer
{
CredentialStore = new SingleUserInMemoryCredentialStore
{
ConsumerKey = "",
ConsumerSecret = "",
AccessToken = "",
AccessTokenSecret = ""
}
};
var context = new TwitterContext(auth);
var uploadedMedia = await context.UploadMediaAsync(File.ReadAllBytes(#image));
var mediaIds = new List<ulong> { uploadedMedia.MediaID };
await context.TweetAsync(
message,
mediaIds
);
}
protected void Page_Load(object sender, EventArgs e)
{
SendTweetWithSinglePicture("test", "path");
}
How can I call a async method on Page_Load?
The question is if you want to make the Page_Load method async or not. If so:
protected async void Page_Load(object sender, EventArgs e)
{
await SendTweetWithSinglePicture("test", "path");
}
Or if you don't want it to be async:
protected void Page_Load(object sender, EventArgs e)
{
SendTweetWithSinglePicture("test", "path").Wait();
}
This does require your async method to return Task as it always should! (except event handlers)
The problem with this might be that the method doesn't complete before rendering the page. If it has to, you'd better make the method synchronous, or register the task using Page.RegisterAsyncTask and Page.ExecuteRegisteredAsyncTasks. Effectively this will freeze the Page_Load method too.
protected void Page_Load(object sender, EventArgs e)
{
PageAsyncTask t = new PageAsyncTask(SendTweetWithSinglePicture("test", "path"));
// Register the asynchronous task.
Page.RegisterAsyncTask(t);
// Execute the register asynchronous task.
Page.ExecuteRegisteredAsyncTasks();
}
You should use PageAsyncTask. It has samples in MSDN page.
// Register the asynchronous task.
Page.RegisterAsyncTask(new PageAsyncTask(SendTweetWithSinglePicture(message, image));
// Execute the register asynchronous task.
Page.ExecuteRegisteredAsyncTasks();
as I pointed the sample and explanations on MSDN page is pretty good.
Try This :
public void Page_Load(object sender, EventArgs e)
{
RegisterAsyncTask(new PageAsyncTask(LoadSomeData));
}
public async Task LoadSomeData()
{
var clientcontacts = Client.DownloadStringTaskAsync("api/contacts");
var clienttemperature = Client.DownloadStringTaskAsync("api/temperature");
var clientlocation = Client.DownloadStringTaskAsync("api/location");
await Task.WhenAll(clientcontacts, clienttemperature, clientlocation);
var contacts = Newtonsoft.Json.JsonConvert.DeserializeObject<List<Contact>>(await clientcontacts);
var location = Newtonsoft.Json.JsonConvert.DeserializeObject<string>(await clientlocation);
var temperature = Newtonsoft.Json.JsonConvert.DeserializeObject<string>(await clienttemperature);
listcontacts.DataSource = contacts;
listcontacts.DataBind();
Temparature.Text = temperature;
Location.Text = location;
}

Convert method to return a task

How can I turn the below method into the right format for returning a task items. The method stub requires a task to be used. This is my first time into async methods I am using it for the windows phone 8 like below:
private System.Threading.Tasks.Task listView_PullToRefreshRequested(object sender, EventArgs e)
{
Populatelist();
}
public async void Populatelist()
{
try
{
curoListsDal _db = new curoListsDal();
cLists = await _db.GetListsAync();
listView.ItemsSource = cLists;
}
catch (Exception ex)
{
}
}
The right format would be to return a Task instead of void in PopulateListAsync and await on that inside your event handler:
private async void PullToRefreshRequestAsync(object sender, EventArgs e)
{
await PopulateListAsync();
}
public async Task PopulateListAsync()
{
curoListsDal db = new curoListsDal();
listView.ItemsSource = await db.GetListsAsync();
}
Side note: don't swallow exceptions.

Await execution of base method in derived event handler

I am trying to get file property in derived custom control. The code is follows:
public partial class ControlBase : UserControl {
public ControlBase() {
this.InitializeComponent();
//Buttons
PickFileButton.Click += pickFile;
}
protected virtual async void pickFile(object sender, RoutedEventArgs e) {
var picker = new FileOpenPicker();
picker.SuggestedStartLocation = PickerLocationId.VideosLibrary;
picker.FileTypeFilter.Add(".wmv");
picker.FileTypeFilter.Add(".mp4");
var file = await picker.PickSingleFileAsync();
if (file == null) return;
inputFile = file;
}
}
public sealed partial class DerivedControl : ControlBase {
protected async override void pickFile(object sender, RoutedEventArgs e) {
base.pickFile(sender, e);
//need to pick file first
var properties = await inputFile.Properties.GetVideoPropertiesAsync();
}
How can I await picker.PickSingleFileAsync() completion? Derived implementation continues befor file has been picked. Thanks in advance!
As you cannot await on async void, i suggest you do it in a way which is awaitable:
protected virtual async void pickFile(object sender, RoutedEventArgs e)
{
await PickFileAsync();
}
protected async Task PickFileAsync()
{
var picker = new FileOpenPicker();
picker.SuggestedStartLocation = PickerLocationId.VideosLibrary;
picker.FileTypeFilter.Add(".wmv");
picker.FileTypeFilter.Add(".mp4");
var file = await picker.PickSingleFileAsync();
if (file == null) return;
inputFile = file;
}
And then inside your derived:
protected async override void pickFile(object sender, RoutedEventArgs e)
{
await base.PickFileAsync();
//need to pick file first
var properties = await inputFile.Properties.GetVideoPropertiesAsync();
}
I assume inputFile is accessible in your derived types. If not, simply return a Task<InputFile> from PickFileAsync
Maybe you lack await keyword in front of base.PickFile(sender, e) ?

Categories

Resources