I have an interface, with an event I want to fire in a mock:
public interface IGpsLocationSource
{
event EventHandler<GpsLocation> GpsLocationUpdated;
}
My test look like this:
var gps = new Mock<IGpsLocationSource>();
gps.Raise(x => x.GpsLocationUpdated += (sender, e) => { }, new GpsLocation(0, 0));
I get the following error:
Result StackTrace:
at Moq.Mock1.Raise(Action1 eventExpression, Object[] args)
at Test.cs:line 27
Result Message: System.Reflection.TargetParameterCountException : Parameter count mismatch.
What am I doing wrong?
I forgot the "sender"
gps.Raise(x => x.GpsLocationUpdated += (sender, e) => { }, this, new GpsLocation(0, 0));
Related
I have a connection with binanceApi and I have a disconnect problem,
the API disconnects and I don't know the reason, I wanna keep the connection alive until I have the orders in position. I will post my code, maybe someone can help me.
I already have created another two projects with websocketsharp on localhost to test and all disconnects fire normally.
https://pastebin.com/edit/2Mbh1X4p
public class WSMonitorada
{
public WebSocket ws;
public Usuario User;
public Timer timerKeepAlive = new Timer();
public WSMonitorada(Usuario user, string key)
{
timerKeepAlive.Interval = TimeSpan.FromMinutes(15).TotalMilliseconds;
timerKeepAlive.Elapsed += (object source, ElapsedEventArgs e) =>
{
BinanceUserDataStream.KeepAlive(User.BinanceAPIKey, user.BinanceAPISecret);
};
timerKeepAlive.Start();
ws = new WebSocket("wss://stream.binance.com:9443/ws/" + key);
ws.WaitTime = TimeSpan.FromSeconds(5);
ws.Log.Level = LogLevel.Trace;
ws.Log.File = "C:\\LogConexao\\" + user.nome + ".txt";
//log file never show close event
ws.OnOpen += (sender, e) =>
{
//logic here wors perfect
};
ws.EmitOnPing = true;
ws.OnMessage += (sender, e) =>
{
if (e.IsPing)
{
ws.Ping();
return;
}
//logic here wors perfect
}
ws.OnClose += (sender, e) =>
{
// i have a logic here to analyse if i have a opened order and reconnect again but event never fire
ws.Connect();
};
ws.Connect();
}
}
I think your Ping is not correct. The server waits for 'pong' message
UPD
According to binance docs =)
I have the following two event handlers for an EditText field, the first one works but the second one did not. I will rather have the second one working because the first event handler requires that the user press the enter key which I suspect not every one will do.
First and working
private decimal paidAmount;
private EditText EditTextPaidAmount;
EditTextPaidAmount = RootView.FindViewById<EditText>(Resource.Id.editTextAmountPaid);
EditTextPaidAmount.KeyPress += (object sender, View.KeyEventArgs e) =>
{
e.Handled = false;
if (e.Event.Action == KeyEventActions.Down && e.KeyCode == Keycode.Enter)
{
paidAmount = Decimal.Parse(EditTextPaidAmount.Text);
RenderInvoiceTotals();
e.Handled = true;
}
};
This here is not working, it throws a System.FormatException "Invalid character at position 0"
EditTextPaidAmount = RootView.FindViewById<EditText>(Resource.Id.editTextAmountPaid);
EditTextPaidAmount.TextChanged += (object sender, Android.Text.TextChangedEventArgs e) =>
{
paidAmount = Decimal.Parse(EditTextPaidAmount.Text, CultureInfo.InvariantCulture);
RenderInvoiceTotals();
};
Maybe you could try using Decimal.TryParse instead?
This code works for me:
edit.TextChanged += (sender, args) =>
{
decimal decimalValue;
var isDecimal = Decimal.TryParse(edit.Text, out decimalValue);
if (isDecimal)
text.Text = decimalValue.ToString();
};
Is the exception coming from RenderInvoiceTotals?
Set the inputType property of the EditText to numberDecimal.
OR
Use Decimal.TryParse to parse the EditText value.
Because the error you have mentioned usually appears due to the parsing of string values to decimal.
Try using EditorAction event
EditTextPaidAmount.EditorAction += (sender, e) =>
{
e.Handled = false;
if (e.ActionId == ImeAction.Send)
{
DoStuff();
e.handled = true;
}
};
http://forums.xamarin.com/discussion/3686/edittext-setoneditoractionlistener-is-this-supported
I'm developing an app and have run into a problem with asynchronous calls... Here's what i'm trying to do.
The app consumes a JSON API, and, when run, fills the ListBox within a panorama item with the necessary values (i.e. a single news article). When a user selects a ListBox item, the SelectionChanged event is fired - it picks up the articleID from the selected item, and passes it to an Update method to download the JSON response for the article, deserialize it with JSON.NET, and taking the user to the WebBrowser control which renders a html page from the response received.
The problem with this is that I have to wait for the response before I start the NavigationService, but I'm not sure how to do that properly. This way, the code runs "too fast" and I don't get my response in time to render the page.
The event code:
private void lstNews_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
if (lstNews.SelectedIndex == -1)
{
return;
}
ShowArticle _article = new ShowArticle();
ListBox lb = (ListBox)sender;
GetArticles item = (GetArticles)lb.SelectedItem;
string passId = ApiRepository.ApiEndpoints.GetArticleResponseByID(item.Id);
App.Current.JsonModel.JsonUri = passId;
App.Current.JsonModel.Update();
lstNews.SelectedIndex = -1;
NavigationService.Navigate(new Uri("/View.xaml?id=" + item.Id, UriKind.Relative));
}
OnNavigatedTo method in the View:
protected override void OnNavigatedTo(System.Windows.Navigation.NavigationEventArgs e)
{
base.OnNavigatedTo(e);
long sentString = long.Parse(NavigationContext.QueryString["id"]);
string articleUri = ApiRepository.ApiEndpoints.GetArticleResponseByID(Convert.ToInt32(sentString));
//this throws an error, runs "too fast"
_article = App.Current.JsonModel.ArticleItems[0];
}
The update method:
public void Update()
{
ShowArticle article = new ShowArticle();
try
{
webClient.DownloadStringCompleted += (p, q) =>
{
if (q.Error == null)
{
var deserialized = JsonConvert.DeserializeObject<ShowArticle>(q.Result);
_articleItems.Clear();
_articleItems.Add(deserialized);
}
};
}
catch (Exception ex)
{
//ignore this
}
webClient.DownloadStringAsync(new Uri(jsonUri));
}
async callback pattern:
public void Update(Action callback, Action<Exception> error)
{
webClient.DownloadStringCompleted += (p, q) =>
{
if (q.Error == null)
{
// do something
callback();
}
else
{
error(q.Error);
}
};
webClient.DownloadStringAsync(new Uri(jsonUri));
}
call:
App.Current.JsonModel.Update(() =>
{
// executes after async completion
NavigationService.Navigate(new Uri("/View.xaml?id=" + item.Id, UriKind.Relative));
},
(error) =>
{
// error handling
});
// executes just after async call above
In rx you can write :
var oe = Observable.FromEventPattern<SqlNotificationEventArgs>(sqlDep, "OnChange");
and then subscribe to the observable to convert the OnChange event on the sqlDep object into an observable.
Similarily, how can you create a Task from a C# event using the Task Parallel Library ?
EDIT: clarification
The solution pointed by Drew and then written explicitely by user375487 works for a single event. As soon as the task finished ... well it is finished.
The observable event is able to trigger again at any time. It is can be seen as an observable stream. A kind of ISourceBlock in the TPL Dataflow. But in the doc http://msdn.microsoft.com/en-us/library/hh228603(v=vs.110).aspx there is no example of ISourceBlock.
I eventually found a forum post explaining how to do that: http://social.msdn.microsoft.com/Forums/en/tpldataflow/thread/a10c4cb6-868e-41c5-b8cf-d122b514db0e
public static ISourceBlock CreateSourceBlock(
Action,Action,Action,ISourceBlock> executor)
{
var bb = new BufferBlock();
executor(t => bb.Post(t), () => bb.Complete(), e => bb.Fault(e), bb);
return bb;
}
//Remark the async delegate which defers the subscription to the hot source.
var sourceBlock = CreateSourceBlock<SomeArgs>(async (post, complete, fault, bb) =>
{
var eventHandlerToSource = (s,args) => post(args);
publisher.OnEvent += eventHandlerToSource;
bb.Complete.ContinueWith(_ => publisher.OnEvent -= eventHandlerToSource);
});
I've not tryed the above code. There may be a mismatch between the async delegate and the definition of CreateSourceBlock.
There is no direct equivalent for the Event Asynchronous Pattern (EAP) baked into the TPL. What you need to do is using a TaskCompletionSource<T> that you signal yourself in the event handler. Check out this section on MSDN for an example of what that would look like which uses WebClient::DownloadStringAsync to demonstrate the pattern.
You can use TaskCompletionSource.
public static class TaskFromEvent
{
public static Task<TArgs> Create<TArgs>(object obj, string eventName)
where TArgs : EventArgs
{
var completionSource = new TaskCompletionSource<TArgs>();
EventHandler<TArgs> handler = null;
handler = new EventHandler<TArgs>((sender, args) =>
{
completionSource.SetResult(args);
obj.GetType().GetEvent(eventName).RemoveEventHandler(obj, handler);
});
obj.GetType().GetEvent(eventName).AddEventHandler(obj, handler);
return completionSource.Task;
}
}
Example usage:
public class Publisher
{
public event EventHandler<EventArgs> Event;
public void FireEvent()
{
if (this.Event != null)
Event(this, new EventArgs());
}
}
class Program
{
static void Main(string[] args)
{
Publisher publisher = new Publisher();
var task = TaskFromEvent.Create<EventArgs>(publisher, "Event").ContinueWith(e => Console.WriteLine("The event has fired."));
publisher.FireEvent();
Console.ReadKey();
}
}
EDIT Based on your clarification, here is an example of how to achieve your goal with TPL DataFlow.
public class EventSource
{
public static ISourceBlock<TArgs> Create<TArgs>(object obj, string eventName)
where TArgs : EventArgs
{
BufferBlock<TArgs> buffer = new BufferBlock<TArgs>();
EventHandler<TArgs> handler = null;
handler = new EventHandler<TArgs>((sender, args) =>
{
buffer.Post(args);
});
buffer.Completion.ContinueWith(c =>
{
Console.WriteLine("Unsubscribed from event");
obj.GetType().GetEvent(eventName).RemoveEventHandler(obj, handler);
});
obj.GetType().GetEvent(eventName).AddEventHandler(obj, handler);
return buffer;
}
}
public class Publisher
{
public event EventHandler<EventArgs> Event;
public void FireEvent()
{
if (this.Event != null)
Event(this, new EventArgs());
}
}
class Program
{
static void Main(string[] args)
{
var publisher = new Publisher();
var source = EventSource.Create<EventArgs>(publisher, "Event");
source.LinkTo(new ActionBlock<EventArgs>(e => Console.WriteLine("New event!")));
Console.WriteLine("Type 'q' to exit");
char key = (char)0;
while (true)
{
key = Console.ReadKey().KeyChar;
Console.WriteLine();
if (key == 'q') break;
publisher.FireEvent();
}
source.Complete();
Console.ReadKey();
}
}
I'm using this to make a web request and download some data:
public partial class MainPage : PhoneApplicationPage
{
public MainPage()
{
InitializeComponent();
var client = new WebClient();
client.DownloadStringCompleted += (s, e) => {
textBlock1.Text = e.Result;
};
client.DownloadStringAsync(new Uri("http://example.com"));
}
}
The text of textBlock1 never changes even though e.Result has the correct data. How do I update that from the callback?
Edit: If I add MessageBox.Show(e.Result); in the callback along with the textBlock1.Text assignment, both the messsage box and the text box show the correct data.
Edit Again: If I add a TextBox and set it's text right after the line textBlock1.Text line, they both show the correct text.
I think, it's a bug.
I also ran into some problems with updating the UI from different dispatchers. What I finally did was use the TextBlock's (or other UI Element) own dispatcher and that worked for me. I think the phone framework may be using different dispatchers between the app and UI Elements. Notice the change from dispatcher.BeginInvoke to textbox1.Dispatcher...
void MainPage_Loaded(object sender, RoutedEventArgs e)
{
var dispatcher = Deployment.Current.Dispatcher;
var client = new WebClient();
client.DownloadStringCompleted += (s, e) =>
{
var result = e.Result;
textBlock1.Dispatcher.BeginInvoke(
()=> textBlock1.Text = result
);
};
client.DownloadStringAsync(new Uri("http://example.com"));
}
From browsing through the WP7 forums, a bunch of people were reporting that this was related to a video card driver issue. I've updated my ATI Radeon HD 3400 drivers to the latest version and it appears to work now.
client.DownloadStringAsync is expecting a Uri like this:
client.DownloadStringAsync(new Uri("http://example.com"));
also, shouldn't you update your TextBlock through a Dispatcher.BeginInvoke like this:
client.DownloadStringCompleted += (s, e) =>
{
if (null == e.Error)
Dispatcher.BeginInvoke(() => UpdateStatus(e.Result));
else
Dispatcher.BeginInvoke(() => UpdateStatus("Operation failed: " + e.Error.Message));
};
public partial class MainPage : PhoneApplicationPage
{
public MainPage()
{
InitializeComponent();
Loaded += MainPage_Loaded;
}
void MainPage_Loaded(object sender, RoutedEventArgs e)
{
var dispatcher = Deployment.Current.Dispatcher;
var client = new WebClient();
client.DownloadStringCompleted += (s, e) =>
{
var result = e.Result;
dispatcher.BeginInvoke(
()=> textBlock1.Text = result
);
};
client.DownloadStringAsync(new Uri("http://example.com"));
}
}
I want to comment but can't yet. Yes, I have a very similar issue. In my case it's my viewmodel that is updating a DownloadStatus property, then when the download is completed I do some more work and continue updating this property.
The view stops updating once the ViewModel code hits the OpenReadCompleted method. I've stepped carefully through the code. PropertyChanged fires, and the view even comes back and retrieves the new property value, but never shows the change.
I was sure it was a bug, but then I created a brand new project to reproduce the issue, and it works fine!
Here's a snippet of my non-reproducing code. The UI textblock bound to "DownloadStatus" happily updates properly all the way through. But the same paradigm doesn't work in my main project. Infuriating!
public void BeginDownload(bool doWorkAfterDownload)
{
DownloadStatus = "Starting ...";
_doExtraWork = doWorkAfterDownload;
var webClient = new WebClient();
string auth = "Basic " + Convert.ToBase64String(System.Text.Encoding.UTF8.GetBytes("test:password"));
webClient.Headers["Authorization"] = auth;
webClient.DownloadProgressChanged += new DownloadProgressChangedEventHandler(webClient_DownloadProgressChanged);
webClient.OpenReadCompleted += new OpenReadCompletedEventHandler(webClient_OpenReadCompleted);
webClient.OpenReadAsync(new Uri("http://www.ben.geek.nz/samsung1.jpg"));
}
void webClient_OpenReadCompleted(object sender, OpenReadCompletedEventArgs e)
{
if (e.Error != null)
{
DownloadStatus = e.Error.Message;
return;
}
DownloadStatus = "Completed. Idle.";
if(_doExtraWork)
{
Thread t = new Thread(DoWork);
t.Start(e.Result);
}
}
void DoWork(object param)
{
InvokeDownloadCompleted(new EventArgs());
// just do some updating
for (int i = 1; i <= 10; i++)
{
DownloadStatus = string.Format("Doing work {0}/10", i);
Thread.Sleep(500);
}
DownloadStatus = "Completed extra work. Idle.";
InvokeExtraWorkCompleted(new EventArgs());
}