Update progress bar from Task.Run async - c#

I have a method to generate software activation key from User Information:
private async void GenerateAsync()
{
await Task.Run(() =>
{
var secretstring = "CustomerName >> " + txtFullname.Text + " >> " + txtproducid.Text;
keymng = new KeyManager(secretstring);
var dateexp = numExpdate.Value;
if (dateexp == 0)
{
dateexp = 730000;
}
if (cbLicenseType.SelectedIndex == 0)
{
kvc = new KeyValueClass()
{
LicenseType = LicenseType.FULL,
Header = Convert.ToByte(9),
Footer = Convert.ToByte(6),
ProductCode = PRODUCTCODE,
Edition = (Edition)Enum.Parse(typeof(Edition), cbEdition.SelectedText),
Version = 1,
Expiration = DateTime.Now.AddDays(Convert.ToInt32(dateexp))
};
if (!keymng.GenerateKey(kvc, ref productkey))
{
//Handling Error
}
}
else
{
kvc = new KeyValueClass()
{
LicenseType = LicenseType.TRIAL,
Header = Convert.ToByte(9),
Footer = Convert.ToByte(6),
ProductCode = PRODUCTCODE,
Edition = (Edition)Enum.Parse(typeof(Edition), cbEdition.SelectedText),
Version = 1,
Expiration = DateTime.Now.AddDays(Convert.ToInt32(dateexp))
};
if (!keymng.GenerateKey(kvc, ref productkey))
{
//Handling Error
}
}
});
}
and I have progressbar. I want to run this method async and update progress to progressbar. How to update UI with async-await method. BackgroundWorker is alternative???

You should use the more modern IProgress<T>/Progress<T> types:
var progress = new Progress<int>(value => { progressBar.Value = value; });
await Task.Run(() => GenerateAsync(progress));
void GenerateAsync(IProgress<int> progress)
{
...
progress?.Report(13);
...
}
This is better than Invoke because it doesn't tie your business logic (GenerateAsync) to a particular UI, or to any UI at all.

I use this method in Winforms:
progressBar1.Invoke((Action)(() => progressBar1.Value=50))

Related

Move an object to Mainthread

I try to process a method asynchronously adn store the result in an ObservableCollection, but I always get the Error
Must create DependencySource on same Thread as the DependencyObject.
This is my Default Code that I try to use for the operation:
The method LoadServiceTasksAsync is called by a button.
public async void LoadServiceTasksAsync(object o)
{
var serviceTasks = await Task.Run(() => repository.GetServiceTasks((string)o));
var serviceTasksViewModels = serviceTasks.Select(m => new ServiceTaskViewModel()
{
OSM = m.OSM,
Priority = "" + m.Priority,
Status = m.Status
});
ServiceTasks = new ObservableCollection<ServiceTaskViewModel>(serviceTasksViewModels);
}
I also have tried to wrap it in a Dispatcher like this:
public async void LoadServiceTasksAsync(object o)
{
var serviceTasks = await Task.Run(() => repository.GetServiceTasks((string)o));
Application.Current.Dispatcher.Invoke(() =>
{
var serviceTasksViewModels = serviceTasks.Select(m => new ServiceTaskViewModel()
{
OSM = m.OSM,
Priority = "" + m.Priority,
Status = m.Status,
});
ServiceTasks = new ObservableCollection<ServiceTaskViewModel>(serviceTasksViewModels);
});
}
I know that I have to create the serviceTaskViewModels in the MainThread but I have no idea how to do that as the serviceTasks are always in another Thread.
EDIT:
var serviceTasks is an IEnumerable<Models.ServiceTask> which are downloaded with a library from a MySQL-Database. The method repository.GetServiceTasks((string)o) itself works fine.
So if I execute var serviceTasks = repository.GetServiceTasks((string)o); there are no problems, except the freezing UI.
I also have only one UI Thread.
Unfortunately I made a mistake while creating the object 'OSM' as there is a little Bitmap created depending of the state of a value.
The assignment of the Bitmap inside the 'OSM'object causes the exception.
The solution for this is to 'Freeze()' the Bitmaps:
async load BitmapImage in C#
In my case it looks like: (Shortened Version)
double? l11 = ERPStockList.getStockLevel(sapc.obj, "680");
if (l11 != null && l11>l1)
{
l1 = (double)ERPStockList.getStockLevel(sapc.obj, "680");
if (l1 >= sapc.iQuantity) { bl1 = toBitmap(File.ReadAllBytes("GreenDot.png")); }
else if (l1 > 0) { bl1 = toBitmap(File.ReadAllBytes("OrangeDot.png")); }
else { bl1 = toBitmap(File.ReadAllBytes("RedDot.png"));
}
OSM osm = new OSM()
{
LO_Acta = bl1,
LO_Windlift = bl2,
LO_Onshore = bl3
};
osm.LO_Acta.Freeze();
osm.LO_Onshore.Freeze();
osm.LO_Windlift.Freeze();
osmList.Add(osm);
The toBitmap-Method:
public BitmapImage toBitmap(Byte[] value)
{
if (value != null && value is byte[])
{
byte[] ByteArray = value as byte[];
BitmapImage bmp = new BitmapImage();
bmp.BeginInit();
bmp.StreamSource = new MemoryStream(ByteArray);
bmp.DecodePixelHeight = 10;
bmp.DecodePixelWidth = 10;
bmp.EndInit();
return bmp;
}
return null;
}

How to make a higher order function for conflict responses c#

I have this function that updates a CouchDB Database but I want it to try updating again if the Response Code is conflict, i want it to have 3 tries, how do I do that?
public async Task<HttpResponseMessage> UpdateRecord(Profile latestProfile)
{
ProfileRecordByUpn profileRecord = await this.GetProfileByUpn(latestProfile);
Profile oldProfile = profileRecord.Rows.First().Value;
var client = this.clientFactory.CreateClient(NamedHttpClients.COUCHDB);
var formatter = new JsonMediaTypeFormatter();
formatter.SerializerSettings = new JsonSerializerSettings
{
Formatting = Formatting.Indented,
ContractResolver = new CamelCasePropertyNamesContractResolver()
};
var query = HttpUtility.ParseQueryString(string.Empty);
query["rev"] = oldProfile.Rev;
//Setting the profile Active = true, because as of now we don't have any UI for disabling the account
latestProfile.Active = oldProfile.Active;
DateTimeOffset now = DateTimeOffset.Now;
latestProfile.Created = oldProfile.Created;
latestProfile.Modified = now;
//This will check if we the InApp boolean value changed then will set date to Enabled/Disabled
if (oldProfile.InApp != latestProfile.InApp)
{
if (latestProfile.InApp == true)
{
latestProfile.InAppEnabled = now;
latestProfile.InAppDisabled = oldProfile.InAppDisabled;
}
else
{
latestProfile.InAppDisabled = now;
latestProfile.InAppEnabled = oldProfile.InAppEnabled;
}
}
else
{
latestProfile.InAppEnabled = oldProfile.InAppEnabled;
latestProfile.InAppDisabled = oldProfile.InAppDisabled;
}
//This will check if we the SMS boolean value changed then will set date to Enabled/Disabled
if (oldProfile.SMS != latestProfile.SMS)
{
if (latestProfile.SMS == true)
{
latestProfile.SMSEnabled = now;
latestProfile.SMSDisabled = oldProfile.SMSDisabled;
}
else
{
latestProfile.SMSDisabled = now;
latestProfile.SMSEnabled = oldProfile.SMSEnabled;
}
}
else
{
latestProfile.SMSEnabled = oldProfile.SMSEnabled;
latestProfile.SMSDisabled = oldProfile.SMSDisabled;
}
//This will check if we the SMS boolean value changed then will set date to Enabled/Disabled
if (oldProfile.Email != latestProfile.Email)
{
if (latestProfile.Email == true)
{
latestProfile.EmailEnabled = now;
latestProfile.EmailDisabled = oldProfile.EmailDisabled;
}
else
{
latestProfile.EmailDisabled = now;
latestProfile.EmailEnabled = oldProfile.EmailEnabled;
}
}
else
{
latestProfile.EmailEnabled = oldProfile.EmailEnabled;
latestProfile.EmailDisabled = oldProfile.EmailDisabled;
}
var response = await this.couchDbClient.AuthenticatedQuery(async (c) => {
return await c.PutAsync($"{API_PROFILES_DB}/{oldProfile.Id.ToString()}?{query}", latestProfile, formatter);
}, NamedHttpClients.COUCHDB, client);
return response;
}
so I will be calling this function from another function? Do I make an another function which is a higher order function and pass this function as a parameter to that higher order function?
Higher-order functions in C# are implemented by methods taking delegates as parameters, usually an Action or Func delegate.
In this case, you should use an established library like Polly.
var policy = Policy
.HandleResult<HttpResponseMessage>(r => r.StatusCode == HttpStatusCode.Conflict)
.RetryAsync(3);
var result = await policy.ExecuteAsync(() => UpdateRecord(latestProfile));
Update to do it yourself (uncompiled and untested code):
async Task<HttpResponseMessage> MyRetry(Func<Task<HttpResponseMessage>> action)
{
for (int retries = 0; retries < 3; ++retries)
{
var result = await action();
if (result.StatusCode != HttpStatusCode.Conflict)
return result;
}
return await action();
}
The above code will retry 3 times, for 4 total calls if it keeps returning Conflict.

call back query data from inline keyboard

I'm trying to get the data from an inline keyboard, I've searched a lot but unfortunately didn't get my answer and non of codes worked for me. Here's my code please help me
static void Main(string[] args){
InlineKeyboardButton[][] buttons =
new InlineKeyboardButton[][]{
new InlineKeyboardButton[]{newInlineKeyboardButton() { Text = "show Channel", CallbackData = "Data1" }},
new InlineKeyboardButton[]{new InlineKeyboardButton() { Text = "show Website", CallbackData = "Data2" }}};
inlineKeyboardMarkup = new InlineKeyboardMarkup() { InlineKeyboard = buttons };
Task.Run(() => RunBot());
Console.ReadLine();
} // End of main method
public static async Task RunBot(){
while (true){
var u = await bot.MakeRequestAsync(new GetUpdates() { Offset
= offset });
foreach (var update in u)
{
offset = update.UpdateId + 1;
var text = update.Message.Text;
// here I want to get the data like this, but it doesn't work
if (update.ChosenInlineResult != null){
Console.WriteLine("Chosen Inline Result: " +
update.ChosenInlineResult.ToString());
}
switch(text){
case "Something":{
var req = new SendMessage(update.Message.Chat.Id, "راهنما") { ReplyMarkup = inlineKeyboardMarkup };
await bot.MakeRequestAsync(req);
break;
}
}
}
}
}
you must replace this
if (update.ChosenInlineResult != null){
Console.WriteLine("Chosen Inline Result: " +
update.ChosenInlineResult.ToString());
}
with something like This :
if (update.CallbackQuery != null)
{
Console.WriteLine(val.CallbackQuery.Message+"-"+val.CallbackQuery.Data);
}

Dynamic change Microsoft BOT Framework Form's Field Step: hiding and showing the confirmation

I'm new to MS BOT Framework.
I changed MS github MultiDialogsBot.sln , I added a HotelsQuery property to init Form's Field value at HotelsDialog.cs,
public class HotelsDialog : IDialog<object>
{
public HotelsQuery _HotelsQuery { get; set; }
public HotelsDialog()
{
_HotelsQuery = new HotelsQuery{
Destination = "Taiwan",
CheckIn = new DateTime(2017,10,29),
Nights = 3
};
}
public async Task StartAsync(IDialogContext context)
{
await context.PostAsync("Welcome to the Hotels finder!");
var hotelsFormDialog = FormDialog.FromForm(this.BuildHotelsForm, FormOptions.PromptInStart);
context.Call(hotelsFormDialog, this.ResumeAfterHotelsFormDialog);
}
public IForm<HotelsQuery> BuildHotelsForm()
{
OnCompletionAsyncDelegate<HotelsQuery> processHotelsSearch = async (context, state) =>
{
await context.PostAsync($"Ok. Searching for Hotels in {state.Destination} from {state.CheckIn.ToString("MM/dd")} to {state.CheckIn.AddDays(state.Nights).ToString("MM/dd")}...");
};
var destField = new FieldReflector<HotelsQuery>(nameof(HotelsQuery.Destination))
.SetActive((state) =>
{
//depend on _HotelsQuery's values
bool isActive = string.IsNullOrWhiteSpace(_HotelsQuery.Destination);
if (!isActive) state.Destination = _HotelsQuery.Destination;
return isActive;
});
var checkInField = new FieldReflector<HotelsQuery>(nameof(HotelsQuery.CheckIn))
.SetActive((state) =>
{
//depend on _HotelsQuery's values
bool isActive = _HotelsQuery.CheckIn == DateTime.MinValue;
if (!isActive) state.CheckIn = _HotelsQuery.CheckIn;
return isActive;
});
var nightsField = new FieldReflector<HotelsQuery>(nameof(HotelsQuery.Nights))
.SetActive((state) =>
{
//depend on _HotelsQuery's values
bool isActive = _HotelsQuery.Nights == 0;
if (!isActive) state.Nights = _HotelsQuery.Nights;
return isActive;
});
var form = new FormBuilder<HotelsQuery>()
.Field(destField)
.Message("Looking for hotels in {Destination}...")
.Field(checkInField)
.Message("Check in {CheckIn}...")
.Field(nightsField)
.Message("Nights : {Nights}...")
.Confirm("Is this your selection?\n {*}", state =>
{
//clean all fields for showing fields in confirmation
_HotelsQuery.Destination = string.Empty;
_HotelsQuery.CheckIn = DateTime.MinValue;
_HotelsQuery.Nights = 0;
return true;
}, new List<string>())
.Message("Thanks you ...")
.OnCompletion(processHotelsSearch)
.Build();
return form;
}
public async Task ResumeAfterHotelsFormDialog(IDialogContext context, IAwaitable<HotelsQuery> result)
{
try
{
var searchQuery = await result;
var hotels = await this.GetHotelsAsync(searchQuery);
await context.PostAsync($"I found in total {hotels.Count()} hotels for your dates:");
var resultMessage = context.MakeMessage();
resultMessage.AttachmentLayout = AttachmentLayoutTypes.Carousel;
resultMessage.Attachments = new List<Attachment>();
foreach (var hotel in hotels)
{
HeroCard heroCard = new HeroCard()
{
Title = hotel.Name,
Subtitle = $"{hotel.Rating} starts. {hotel.NumberOfReviews} reviews. From ${hotel.PriceStarting} per night.",
Images = new List<CardImage>()
{
new CardImage() { Url = hotel.Image }
},
Buttons = new List<CardAction>()
{
new CardAction()
{
Title = "More details",
Type = ActionTypes.OpenUrl,
Value = $"https://www.bing.com/search?q=hotels+in+" + HttpUtility.UrlEncode(hotel.Location)
}
}
};
resultMessage.Attachments.Add(heroCard.ToAttachment());
}
await context.PostAsync(resultMessage);
}
catch (FormCanceledException ex)
{
string reply;
if (ex.InnerException == null)
{
reply = "You have canceled the operation. Quitting from the HotelsDialog";
}
else
{
reply = $"Oops! Something went wrong :( Technical Details: {ex.InnerException.Message}";
}
await context.PostAsync(reply);
}
finally
{
context.Done<object>(null);
}
}
private async Task<IEnumerable<Hotel>> GetHotelsAsync(HotelsQuery searchQuery)
{
var hotels = new List<Hotel>();
// Filling the hotels results manually just for demo purposes
for (int i = 1; i <= 5; i++)
{
var random = new Random(i);
Hotel hotel = new Hotel()
{
Name = $"{searchQuery.Destination} Hotel {i}",
Location = searchQuery.Destination,
Rating = random.Next(1, 5),
NumberOfReviews = random.Next(0, 5000),
PriceStarting = random.Next(80, 450),
Image = $"https://placeholdit.imgix.net/~text?txtsize=35&txt=Hotel+{i}&w=500&h=260"
};
hotels.Add(hotel);
}
hotels.Sort((h1, h2) => h1.PriceStarting.CompareTo(h2.PriceStarting));
return hotels;
}
}
I have trouble after the confirmation shows. When a user answers yes, BOT will ask CheckIn's prompt.
Why does it not go to the OnCompletion event?
Thanks for your help.
You are clearing out the values in the .Confirm
Try something like this:
var form = new FormBuilder<HotelsQuery>()
.Field(destField)
.Message("Looking for hotels in {Destination}...")
.Field(checkInField)
.Message("Check in {CheckIn}...")
.Field(nightsField)
.Message("Nights : {Nights}...")
.Confirm("Is this your selection?\n {*}", state =>
{
if (_HotelsQuery.Destination == string.Empty ||
_HotelsQuery.CheckIn == DateTime.MinValue ||
_HotelsQuery.Nights == 0)
return false;
return true;
}, new List<string>())
.Message("Thanks you ...")
.OnCompletion(processHotelsSearch)
.Build();

How to wait for an asynchronization method in silverlight

I have made two functions in a WCF service and call them in silverlight using asynchronization. I call one method after the other, but before completion of the first method, silverlight executes the second method. I want the first method to completely finish executing before the second method call.
thanks for your reply i m pasting my code please suggest in code how i implement.
private GDOperations.GDDoneOperationsClient _gdDoneOperation;
private ImageOperationsClient proxy = null;
foreach (var file in _filesCollection)
{
clsImageTransactionEntity _clsImageEntity = new clsImageTransactionEntity();
_clsImageEntity.ImageByte = GetFileData(file.OpenRead());
_clsImageEntity.ImageExtension = file.Extension;
_clsImageEntity.ImageName = file.Name;
_clsImageEntity.ImageType = 2;
_clsImageEntity.ImagePath = "~/CMSImages/FinalImages/" + lblSelectedBarcode.Content.ToString() + "/" + file.Name;
_clsImageEntity.JabongBarcode = lblSelectedBarcode.Content.ToString();
GDOperations.clsImageTransactionEntity _clsImageGDEntity = new GDOperations.clsImageTransactionEntity();
_clsImageGDEntity.ImageExtension = file.Extension;
_clsImageGDEntity.ImageName = file.Name;
_clsImageGDEntity.ImageType = 2;
_clsImageGDEntity.ImagePath = "~/CMSImages/FinalImages/" + lblSelectedBarcode.Content.ToString() + "/" + file.Name;
_clsImageGDEntity.JabongBarcode = lblSelectedBarcode.Content.ToString();
_clsImageGDEntity.RoleId = roleID;
_clsImageGDEntity.TaskID = taskID;
_clsImageGDEntity.UserID = UserId;
_clsImageGDEntity.SystemIP = systemIP;
_clsGdAllotment.clsImageTransactionEntity.Add(_clsImageGDEntity);
----- first method calling-----
proxy.UploadFinalImageCompleted += (s, e) =>
{
if (e.Error == null)
{
}
};
proxy.UploadFinalImageAsync(_clsImageEntity);
countfile = countfile + 1;
pbUploadFiles.Value = countfile;
}
_clsGdAllotment.GdID = int.Parse(lblUserID.Content.ToString());
_clsGdAllotment.JabongBarcode = lblSelectedBarcode.Content.ToString();
_clsGdAllotment.TaskID = taskID;
--- after for loop completion calling second method -----
_gdDoneOperation.InsertGDDoneInformationCompleted += _gdDoneOperation_InsertGDDoneInformationCompleted;
_gdDoneOperation.InsertGDDoneInformationAsync(_clsGdAllotment);`
Please help its urgent.
If you're using Task-Based Async Pattern:
var task1 = CallFirstAsyncMethod();
task1.Wait(); // waiting task to finish
var task2 = CallAnotherAsyncMethod();
// or subscribe to the task continuation to call second
// method when first operation will finished
task1.ContinueWith(t =>
{
// add error handling
var task2 = CallAnotherAsyncMethod();
});
If you're using Classical Async Pattern (a.k.a. APM):
IAsyncResult ar1 = CallFirstAsyncMethod();
ar1.WaitHandle.Wait();
IAsyncResult ar2 = CallSecondAsyncMethod();
// or use the same technique asynchronously
CallFirstAsyncMethod(ar => // Suppose we should provide appropriate callback
{
// Call to appropriate EndInvoke method
IAsyncResult ar2 = CallSecondAsyncMethod();
}, state);
You can call the second in the callback of the first, no ?
Or is Visual Studio < 2012
You can use AutoResetEvent :
MyServiceClient clientService;
AutoResetEvent autoResetEvent = new AutoResetEvent(false);
public void Execute()
{
InvokeCompletedEventArgs data = null;
clientService.InvokeCompleted += (e, f) =>
{
data = f;
autoResetEvent.Set();
};
m_proxy.MyCallAync();
autoResetEvent.WaitOne(); // Wait the set of autoResetEvent
m_proxy.MySecondCallAync(data); // Data return by the first call
}
Antoine

Categories