I have this method:
public void Handle(ShipmentConfirmedEvent message)
{
try
{
var trackingOrderDto = new ShipmentConfirmedDto
{
AccountId = message.AccountId,
FirstName = message.CustomerFirstName,
TransactionId = message.TransactionId,
Language = message.LanguageCode,
ExcludedCommunicationChannels = message.ExcludedCommunicationChannels,
TrackingId = message.TrackingNumber
};
Log.Info("Received notify of Shipment Confirmed request with id <{0}> for order {1}", message.GenerationId, message.TransactionId);
if (!string.IsNullOrEmpty(_iosForcePushAccountId))
{
Log.Info("Per device Ios, l'accountId {0} verrĂ forzato a {1} per configurazione", trackingOrderDto.AccountId, _iosForcePushAccountId);
trackingOrderDto.AccountId = Convert.ToInt64(_iosForcePushAccountId);
}
Log.Debug("Send push notification for IOS for AccountId <{0}>", trackingOrderDto.AccountId);
var iosContent = _sender.Create(trackingOrderDto, "IOS");
_sender.IosSend(iosContent);
trackingOrderDto.AccountId = message.AccountId;
if (!string.IsNullOrEmpty(_androidForcePushAccountId))
{
Log.Info("Per device Android, l'accountId {0} verrĂ forzato a {1} per configurazione", trackingOrderDto.AccountId, _androidForcePushAccountId);
trackingOrderDto.AccountId = Convert.ToInt64(_androidForcePushAccountId);
}
Log.Debug("Send push notification for Android for AccountId <{0}>", trackingOrderDto.AccountId);
var androidContent = _sender.Create(trackingOrderDto, "ANDROID");
_sender.AndroidSend(androidContent);
}
catch (ExcludedCommunicationChannelsException ex)
{
Log.Warn(ex.Message);
}
catch (Exception ex)
{
var msg = String.Format("Errore durante la gestione del messaggio relativo al PushNotification for username {0}", message.MailTo.First().Address);
Log.Error(ex, msg);
throw new Exception(ex.Message, ex);
}
Log.Info("<{0}> Processed", message.GenerationId);
}
and I have this test:
[Fact]
public void GivenAnOrderConfirmedEventWithForcedAccountId_WhenHandle_ThenCallSenderWithTheForcedAccountId()
{
NServiceBus.Testing.Test.Initialize();
var service = new ShipmentConfirmedRequestEventConsumer(mockSender, "1111", "2222");
NServiceBus.Testing.Test.Handler(svc => service)
.OnMessage<ShipmentConfirmedEvent>(
m =>
{
m.AccountId = 407716;
m.CustomerFirstName = "Marco";
m.TransactionId = "T123456";
m.LanguageCode = "IT";
m.TrackingNumber = "642167921";
}
);
mockSender.AssertWasCalled(x => x.Create(Arg<ShipmentConfirmedDto>.Matches(dto => dto.AccountId == 2222), Arg<string>.Is.Equal("ANDROID")));
mockSender.AssertWasCalled(x => x.Create(Arg<ShipmentConfirmedDto>.Matches(dto => dto.AccountId == 1111), Arg<string>.Is.Equal("IOS")));
}
the second AssertWasCalled, the one related to IOS, throw exception because it seems to be overwritten, being within the method the first to be called.
I need to verify that the Create method is called twice within the method, with the parameters specified.
How can I modify the test in order to verify it?
The solution is to modify test this way:
[Fact]
public void GivenAnOrderConfirmedEventWithForcedAccountId_WhenHandle_ThenCallSenderWithTheForcedAccountId()
{
NServiceBus.Testing.Test.Initialize();
mockSender.Expect(x => x.Create(Arg<ShipmentConfirmedDto>.Matches(dto => dto.AccountId == 2222), Arg<string>.Is.Equal("ANDROID"))).Return(string.Empty);
mockSender.Expect(x => x.Create(Arg<ShipmentConfirmedDto>.Matches(dto => dto.AccountId == 1111), Arg<string>.Is.Equal("IOS"))).Return(string.Empty);
var service = new ShipmentConfirmedRequestEventConsumer(mockSender, "1111", "2222");
NServiceBus.Testing.Test.Handler(svc => service)
.OnMessage<ShipmentConfirmedEvent>(
m =>
{
m.AccountId = 407716;
m.CustomerFirstName = "Marco";
m.TransactionId = "T123456";
m.LanguageCode = "IT";
m.TrackingNumber = "642167921";
}
);
mockSender.VerifyAllExpectations();
}
Related
I am trying to create functionality to copy data from one order to another. Here is the code that copies the data:
protected void copySeminarIDButton_Click(object sender, EventArgs e)
{
try
{
//show some message incase validation failed and return
String seminarID = this.copySeminarIDText.Text;
Int32 id;
try
{
id = Convert.ToInt32(seminarID);
} catch (Exception e2)
{
return;
}
//copy over all the registration types now for the entered id
using (SeminarGroupEntities db = new SeminarGroupEntities())
{
var seminars = db.seminars.Where(x => x.id == id);
if (seminars.Any())
{
var s = seminars.First();
//Load RegTypes
try
{
var regList = s.seminar_registration_type
.OrderBy(x => x.sort)
.ToList()
.Select(x => new seminarRegistrationTypeListing
{
id = x.id,
amount = x.amount,
description = x.description,
feeTypeId = x.feeTypeId,
method = x.method,
promoCodes = PromoCodesToString(x.xref_reg_type_promo.Select(z => z.promoId).ToList()),
title = x.title,
isPreorder = x.isPreorder,
sort = x.sort
});
this.dlTypes.DataSource = regList;
this.dlTypes.DataBind();
}
catch (Exception ex)
{
Response.Write("RegTypes: " + ex.Message);
}
} else
{
return;
}
}
}
catch (Exception m)
{
}
}
The user will enter a ID of the invoice they want to copy from. The above code copies pull the right data from the invoice and loads it on the page. When i click save the data is being saved.
The problem that is occurring is that the invoice that i copy data from will no longer have the data any more. So basically instead of copying the data its actually moving the data to the new invoice. I want to copy.
Here is my Save code.
private void SaveRegTypes(int seminarId)
{
//Reg Types
using (SeminarGroupEntities db = new SeminarGroupEntities())
{
try
{
var s = db.seminars.Where(x => x.id == seminarId).First();
var msg = "alert('Saving:" + seminarId + "');";
ScriptManager.RegisterStartupScript(this.Page, this.Page.GetType(), "Data Copied...", msg, true);
this.copySeminarIDText.Text = msg;
//s.seminar_registration_type.Clear();
foreach (DataListItem dli in this.dlTypes.Items)
{
String sId = ((HiddenField)dli.FindControl("hdnId")).Value;
var reg = new seminar_registration_type();
if ((sId != "") && (sId != "0"))
{
Int32 id = Convert.ToInt32(sId);
reg = db.seminar_registration_type.Where(x => x.id == id).Single();
ScriptManager.RegisterStartupScript(this.Page, this.Page.GetType(), "Data Copied...", "alert('hidded field id is empty.');", true);
}
else
{
db.seminar_registration_type.Add(reg);
}
reg.feeTypeId = Convert.ToInt32(((DropDownList)dli.FindControl("ddlRegType")).SelectedItem.Value);
reg.amount = Convert.ToDecimal(((TextBox)dli.FindControl("txtPrice")).Text);
reg.title = ((DropDownList)dli.FindControl("ddlRegType")).SelectedItem.Text;
reg.description = ((TextBox)dli.FindControl("txtRegDesc")).Text;
reg.method = Convert.ToInt32(((DropDownList)dli.FindControl("ddlDeliveryMethod")).Text);
reg.promocode = null;
reg.isPreorder = Convert.ToBoolean(((CheckBox)dli.FindControl("chkPreorder")).Checked);
reg.sort = 1;
reg.seminarId = seminarId;
string sort = ((TextBox)dli.FindControl("txtRTSort")).Text;
try
{
reg.sort = Convert.ToInt32(sort);
}
catch (Exception ex) { }
//Do Promo Codes
Repeater rptPromocodes = (Repeater)dli.FindControl("rptPromoCodesList");
reg.xref_reg_type_promo.Clear();
foreach (RepeaterItem ri in rptPromocodes.Items)
{
try
{
Int32 id = Convert.ToInt32(((HiddenField)ri.FindControl("hdnCodeId")).Value);
DateTime? expires = null;
try
{
HiddenField exp = (HiddenField)ri.FindControl("hdnExpirationDate");
if (!String.IsNullOrWhiteSpace(exp.Value))
expires = Convert.ToDateTime(((HiddenField)ri.FindControl("hdnExpirationDate")).Value);
}
catch (Exception ex) { }
var code = db.promo_code.Where(x => x.id == id).First();
reg.xref_reg_type_promo.Add(new xref_reg_type_promo
{
expiration = expires,
promoId = code.id
});
}
catch (Exception ex) { }
}
db.SaveChanges();
((HiddenField)dli.FindControl("hdnId")).Value = reg.id.ToString();
}
}
catch (Exception ex)
{
String err = ex.Message;
}
}
}
i've translated the quickblox's sample app for Xamarin forms in Xamarin iOS and Android native.
Everything works "except" that the retrieving of the message fails.
I send the message from one client, and the event is catched from the other chat occupant:
XMPP: DispatchEvents ====> <message id="580735ed335fb760ae0017ec" xmlns="jabber:client" from="18029700-46533#chat.quickblox.com/1220770403-quickblox-68179" type="chat" to="18976912-46533#chat.quickblox.com"><extraParams xmlns="jabber:client"><save_to_history>1</save_to_history><dialog_id>5800aea1a28f9a1c1f000010</dialog_id><message_id>580735ed335fb760ae0017ec</message_id><date_sent>1476867565</date_sent></extraParams><body>test+message</body><thread>5800aea1a28f9a1c1f000010</thread></message>
XMPP: OnMessageReceived ====> From: 18029700 To: 18976912 Body: DateSent 1476867565 FullXmlMessage: <message id="580735ed335fb760ae0017ec" xmlns="jabber:client" from="18029700-46533#chat.quickblox.com/1220770403-quickblox-68179" type="chat" to="18976912-46533#chat.quickblox.com"><extraParams xmlns="jabber:client"><save_to_history>1</save_to_history><dialog_id>5800aea1a28f9a1c1f000010</dialog_id><message_id>580735ed335fb760ae0017ec</message_id><date_sent>1476867565</date_sent></extraParams><body>test+message</body><thread>5800aea1a28f9a1c1f000010</thread></message>
as you can see the Body part into the event OnMessageReceived is empty!
But the html part in the end of this snippet contains the message "test+message"
this is the PrivateChat Class
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using QbChat.Pcl.Repository;
using Quickblox.Sdk.GeneralDataModel.Models;
using Quickblox.Sdk.Modules.ChatXmppModule;
using Quickblox.Sdk.Modules.UsersModule.Models;
using UIKit;
using Xmpp.Im;
namespace KeepInTouch.iOS
{
public partial class PrivateChat : BaseChat
{
PrivateChatManager privateChatManager;
public PrivateChat(string dialogId, string nibname) : base(dialogId, nibname) { }
public async override void ViewWillAppear(bool animated)
{
base.ViewWillAppear(animated);
AppDelegate.R.NavController.SetNavigationBarHidden(true, true);
await MessageProvider.Reconnect();
}
public override void ViewDidLoad()
{
base_tb_chat = tb_chat;
base_txt_chat = txt_chat;
base.ViewDidLoad();
view_top.BackgroundColor = UIColor.FromPatternImage(UIImage.FromFile("navbar_top_kit.png"));
tb_chat.TableFooterView = new UIView();
IsBusyIndicatorVisible = true;
var dialog = Database.Instance().GetDialog(dialogId);
var opponentId = dialog.OccupantIds.Split(',').Select(int.Parse).First(id => id != QbChat.UserId);
ChatXmppClient xmpc = QbChat.QbProvider.GetXmppClient();
privateChatManager = xmpc.GetPrivateChatManager(opponentId, dialogId);
privateChatManager.MessageReceived += OnMessageReceived;
DialogName = dialog.Name;
//xmpc.MessageReceived += OnMessageReceived;
btn_chat.TouchUpInside += async delegate {
await SendMessageCommandExecute();
txt_chat.Text = "";
};
txt_chat.ShouldReturn += (textField) => {
textField.ResignFirstResponder();
return true;
};
txt_chat.EditingChanged += async delegate {
MessageText = txt_chat.Text;
await MessageProvider.Reconnect();
};
btn_back.TouchUpInside += delegate {
DismissViewController(false, null);
};
IsBusyIndicatorVisible = true;
Task.Factory.StartNew(async () => {
var users = await QbChat.QbProvider.GetUsersByIdsAsync(dialog.OccupantIds);
var opponentUser = users.FirstOrDefault(u => u.Id != QbChat.UserId);
if (opponentUser != null && opponentUser.BlobId.HasValue) {
await QbChat.QbProvider.GetImageAsync(opponentUser.BlobId.Value).ContinueWith((task, result) => {
//var bytes =
task.ConfigureAwait(true).GetAwaiter().GetResult();
}, TaskScheduler.FromCurrentSynchronizationContext());
}
opponentUsers = new List<User> { opponentUser };
await LoadMessages();
InvokeOnMainThread(() =>
IsBusyIndicatorVisible = false
);
});
}
async void OnMessageReceived(object sender, MessageEventArgs messageEventArgs)
{
if (messageEventArgs.MessageType == MessageType.Chat ||
messageEventArgs.MessageType == MessageType.Groupchat) {
string decodedMessage = System.Net.WebUtility.UrlDecode(messageEventArgs.Message.MessageText);
var messageTable = new MessageTable();
messageTable.SenderId = messageEventArgs.Message.SenderId;
messageTable.DialogId = messageEventArgs.Message.ChatDialogId;
messageTable.DateSent = messageEventArgs.Message.DateSent;
if (messageEventArgs.Message.NotificationType != 0) {
if (messageEventArgs.Message.NotificationType == NotificationTypes.GroupUpdate) {
if (messageEventArgs.Message.AddedOccupantsIds.Any()) {
var userIds = new List<int>(messageEventArgs.Message.AddedOccupantsIds);
userIds.Add(messageEventArgs.Message.SenderId);
var users = await QbChat.QbProvider.GetUsersByIdsAsync(string.Join(",", userIds));
var addedUsers = users.Where(u => u.Id != messageEventArgs.Message.SenderId);
var senderUser = users.First(u => u.Id == messageEventArgs.Message.SenderId);
messageTable.Text = senderUser.FullName + " added users: " + string.Join(",", addedUsers.Select(u => u.FullName));
} else if (messageEventArgs.Message.DeletedOccupantsIds.Any()) {
var userIds = new List<int>(messageEventArgs.Message.DeletedOccupantsIds);
var users = await QbChat.QbProvider.GetUsersByIdsAsync(string.Join(",", userIds));
messageTable.Text = string.Join(",", users.Select(u => u.FullName)) + " left this room";
}
//var dialogInfo = await QbChat.QbProvider.GetDialogAsync(messageEventArgs.Message.ChatDialogId);
//if (dialogInfo == null)
//{
// return;
//}
//var dialog = new DialogTable(dialogInfo);
//Database.Instance().SaveDialog(dialog);
}
} else {
messageTable.Text = decodedMessage;
}
await SetRecepientName(messageTable);
Messages.Add(messageTable);
InvokeOnMainThread(async () => {
tb_chat.ReloadData();
await ScrollList();
});
}
}
public async Task LoadMessages()
{
List<Message> messages;
try {
messages = await QbChat.QbProvider.GetMessagesAsync(dialogId);
} catch (Exception ex) {
Console.WriteLine(ex);
return;
}
if (messages != null) {
messages = messages.OrderBy(message => message.DateSent).ToList();
foreach (var message in messages) {
var chatMessage = new MessageTable();
chatMessage.DateSent = message.DateSent;
chatMessage.SenderId = message.SenderId;
chatMessage.MessageId = message.Id;
if (message.RecipientId.HasValue)
chatMessage.RecepientId = message.RecipientId.Value;
chatMessage.DialogId = message.ChatDialogId;
chatMessage.IsRead = message.Read == 1;
await SetRecepientName(chatMessage);
chatMessage.Text = System.Net.WebUtility.UrlDecode(message.MessageText);
InvokeOnMainThread(() =>
Messages.Add(chatMessage)
);
}
InvokeOnMainThread(async () => {
tb_chat.ReloadData();
await ScrollList();
});
}
}
async Task SendMessageCommandExecute()
{
var message = MessageText != null ? MessageText.Trim() : string.Empty;
if (!string.IsNullOrEmpty(message)) {
var m = new MessageTable();
m.SenderId = QbChat.UserId;
m.Text = message;
m.DialogId = dialogId;
m.RecepientFullName = "Me";
try {
await MessageProvider.Reconnect();
var encodedMessage = System.Net.WebUtility.UrlEncode(message);
privateChatManager.SendMessage(encodedMessage);
} catch (Exception ex) {
Console.WriteLine(ex);
return;
}
long unixTimestamp = DateTime.UtcNow.Ticks - new DateTime(1970, 1, 1).Ticks;
unixTimestamp /= TimeSpan.TicksPerSecond;
m.DateSent = unixTimestamp;
m.ID = Database.Instance().SaveMessage(m);
var dialog = Database.Instance().GetDialog(dialogId);
dialog.LastMessage = m.Text;
dialog.LastMessageSent = DateTime.UtcNow;
Database.Instance().SaveDialog(dialog, true);
Messages.Add(m);
MessageText = "";
InvokeOnMainThread(async () => {
tb_chat.ReloadData();
await ScrollList();
});
}
}
public override void DidReceiveMemoryWarning()
{
base.DidReceiveMemoryWarning();
}
}
}
long story short the sdk receive the message but apparently fail to parse the body message. fire the handler but if empty don't call the privateChatManager.MessageReceived.
could anyone help please?
Thank you
For Update campaign I am using this Code
public async Task<List<long?>> updateCampaign(Campaign campaign,string status)
{
try
{
campaign.Status = (CampaignStatus)(int)Enum.Parse(typeof(CampaignStatus), status);
var request = new UpdateCampaignsRequest
{
Campaigns = new Campaign[] { campaign },
CustomerId = "xxxxxx",
UserName = "something#outlook.com",
Password = "something#123",
ApplicationToken = "myApplicationToken",
CustomerAccountId = "123456",
DeveloperToken = "1234567890"
};
CampaignService = new ServiceClient<ICampaignManagementService>(_authorizationData);
CampaignService.RefreshOAuthTokensAutomatically = false;
var result = (await CampaignService.CallAsync((s, r) => s.UpdateCampaignsAsync(r), request));
if (result.TrackingId != null)
{
return result.CampaignIds.ToList();
}
else
{
return new List<long?>();
}
}
catch (Exception ex)
{
ErrorLog.log(ex);
return new List<long?>();
}
}
When I run this code, I got this error "Invalid client data. Check the SOAP fault details for more information"
thanks.
For updating the Campaign we can use "BulkServiceManager" for bulk updating of the campaign,you can use this service single campaign update also.
public async Task<List<long?>> updateCampaign(List<Campaign> campaigns)
{
try
{
var listBulkCampaign = new List<BulkCampaign>();
foreach (var campaign in campaigns)
{
var _bulkCampaign = new BulkCampaign()
{
Campaign = campaign
};
listBulkCampaign.Add(_bulkCampaign);
}
BulkServiceManager bulkServiceManager = new BulkServiceManager(_authorizationData);
string fileName = bingCampaignUpdate.csv;
var campaigns = (await bulkServiceManager.UploadEntitiesAsync(new EntityUploadParameters
{
Entities = listBulkCampaign,
OverwriteResultFile = true,
ResultFileDirectory = FileDirectory,
ResultFileName = fileName,
ResponseMode = ResponseMode.ErrorsAndResults
})).OfType<BulkCampaign>().ToList();
return new List<long?>();
}
catch (Exception ex)
{
ErrorLog.log(ex);
return new List<long?>();
}
}
You have to download .csv report and update the Campaigns.
I hope it helps you
I try to test my custom RepositoryHub which inherits base class Hub (implements IHub interface). I mocked all necessary properties of IHub and one his method call which i want to test. Method call was imitated as call from derived custom class RepositoyHub:
hubMock.Setup(p => p.OnConnected()).Returns(new RepositoryHub().OnConnected());
The problem is that method don't have access to mocked IHub fields.
[TestMethod]
public void Is_OnConnected_Successive_When_Instances_is_Absent_And_User_Authenticated()
{
try
{
var connectionId = "1";
var request = new Mock<IRequest>();
request.Setup(s => s.User.Identity.Name).Returns(user + "&" + server + "&" + password + "&" + level);
request.Setup(s => s.User.Identity.IsAuthenticated).Returns(true);
var mockClients = new Mock<IHubCallerConnectionContext>();
var mockGroupManager = new Mock<IGroupManager>();
var mockHubCallerContext = new Mock<HubCallerContext>(request.Object, connectionId);
var hubMock = new Mock<IHub>();
hubMock.Setup(p => p.Groups).Returns(mockGroupManager.Object);
hubMock.Setup(p => p.Context).Returns(mockHubCallerContext.Object);
hubMock.Setup(p => p.Clients).Returns(mockClients.Object);
//Mock virtual method call
hubMock.Setup(p => p.OnConnected()).Returns(new RepositoryHub().OnConnected());
var r = hubMock.Object.OnConnected();
}
catch (Exception ex)
{
throw;
}
}
// Here method which i want to test with mocked IGroupManager, HubCallerContext and IHubCallerConnectionContext
public partial class RepositoryHub: Hub
{
public override Task OnConnected()
{
try
{
var userProfile = new UserProfile(Context.User);
//NullReference exception Context == null, but why i got it if mocked
//HubCallerContext in test method
Groups.Add(Context.ConnectionId, userProfile.ServerUrl);
// and other useful actions
return base.OnConnected();
}
catch (Exception ex)
{
Log.TraceError(String.Format(" Hub: OnConnected() {0}", ex.Message));
throw;
}
}
}
I figure out easy way as for me. Thanks for attention!
var repository = new RepositoryHub(){ Context = mockHubCallerContext.Object,
Clients = mockClients.Object,
Groups = mockGroupManager.Object };
var r = repository.OnConnected();
For JohnB, answer for your last question:
[TestMethod]
public void Is_OnConnected_Successive()
{
const string connectionId = "1";
dynamic groupName = new ExpandoObject();
var IsSendMessageCalled = false;
groupName.sendMessage = new Action<object>((message) =>
{
IsSendMessageCalled = true;
Debug.WriteLine("sendMessage was called, message: {0}", message);
});
var request = new Mock<IRequest>();
request.Setup(s => s.User.Identity.Name).Returns(user + "&" + server + "&" + password + "&" + level);
request.Setup(s => s.User.Identity.IsAuthenticated).Returns(true);
var mockClients = new Mock<IHubCallerConnectionContext>();
mockClients.Setup(m => m.Group("groupName")).Returns((ExpandoObject)groupName);
var mockGroupManager = new Mock<IGroupManager>();
var mockHubCallerContext = new Mock<HubCallerContext>(request.Object, connectionId);
var hub = new RepositoryHub()
{
Context = mockHubCallerContext.Object,
Clients = mockClients.Object,
Groups = mockGroupManager.Object
};
var testMethod = hub.OnConnected();
Thread.Sleep(threadSleepTime);
//or testMethod.Wait();
Assert.IsTrue(IsSendMessageCalled);
}
Let suggest, here you call your sendMessage(message) method:
public override Task OnConnected()
{
Hub.Clients.Group("groupName").sendMessage("Hello ! for groupName group ");
}
Yesterday I've found out how to create several async http requests without async/await. But today I need to do it in a loop: if some of responses don't satisfy some condition - I need to change a request for them and send these requests again. It may be repeated several times.
I've tried this code:
do
{
var loadingCoordinatesTasks = new List<Task<Terminal>>();
var totalCountOfTerminals = terminalPresetNode.ChildNodes.Count;
var uiTaskScheduler = TaskScheduler.FromCurrentSynchronizationContext();
foreach (var terminal in terminals.Except(_terminalsWithCoordinates))
{
var address = terminal.GetNextAddress();
var webRequest = (HttpWebRequest)WebRequest.Create(GeoCoder.GeoCodeUrl + address);
var webRequestTask = Task.Factory.FromAsync<WebResponse>(webRequest.BeginGetResponse,
webRequest.EndGetResponse,
terminal);
var parsingTask = webRequestTask.ContinueWith(antecedent =>
{
// Parse the response
});
loadingCoordinatesTasks.Add(parsingTask);
}
Task.Factory.ContinueWhenAll(loadingCoordinatesTasks.ToArray(), antecedents =>
{
foreach (var antecedent in antecedents)
{
var terminalWithCoordinates = antecedent.Result;
if (antecedent.Status == TaskStatus.RanToCompletion &&
!terminalWithCoordinates.Coordinates.AreUnknown)
{
_terminalsWithCoordinates.Add(terminalWithCoordinates);
_countOfProcessedTerminals++;
}
}
});
} while (_countOfProcessedTerminals < totalCountOfTerminals);
but is it possible to check the condition in while just after every single set of requests executed?
You can perform the check after increasing the count:
_countOfProcessedTerminals++;
if (_countOfProcessedTerminals >= totalCountOfTerminals)
{
break;
}
Is _countOfProcessedTerminals thread-safe though?
I manage to do it using recursion:
public void RunAgainFailedTasks(IEnumerable<Task<Terminal>> tasks)
{
Task.Factory.ContinueWhenAll(tasks.ToArray(), antecedents =>
{
var failedTasks = new List<Task<Terminal>>();
foreach (var antecedent in antecedents)
{
var terminal = antecedent.Result;
// Previous request was failed
if (terminal.Coordinates.AreUnknown)
{
string address;
try
{
address = terminal.GetNextAddress();
}
catch (FormatException) // No versions more
{
continue;
}
var getCoordinatesTask = CreateGetCoordinatesTask(terminal, address);
failedTasks.Add(getCoordinatesTask);
}
else
{
_terminalsWithCoordinates.Add(terminal);
}
}
if (failedTasks.Any())
{
RunAgainFailedTasks(failedTasks);
}
else
{
// Display a map
}
}, CancellationToken.None,
TaskContinuationOptions.None,
TaskScheduler.FromCurrentSynchronizationContext());
}
private Task<Terminal> CreateGetCoordinatesTask(Terminal terminal, string address)
{
var webRequest = (HttpWebRequest)WebRequest.Create(GeoCoder.GeoCodeUrl + address);
webRequest.KeepAlive = false;
webRequest.ProtocolVersion = HttpVersion.Version10;
var webRequestTask = Task.Factory.FromAsync<WebResponse>(webRequest.BeginGetResponse,
webRequest.EndGetResponse,
terminal);
var parsingTask = webRequestTask.ContinueWith(webReqTask =>
{
// Parse the response
});
return parsingTask;
}