How to broadcast real-time data in SignalR? - c#

I have a timer in Global.asax, which calls a method to send current time to all clients through SignalR every 5 seconds:
protected void Application_Start(object sender, EventArgs e)
{
RouteTable.Routes.MapHubs();
var timer = new System.Timers.Timer();
timer.Elapsed += new System.Timers.ElapsedEventHandler(timer_Elapsed);
timer.Interval = 5000;
timer.Enabled = true;
}
void timer_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
{
var context = GlobalHost.ConnectionManager.GetHubContext<EventHub>();
context.Clients.All.Send(DateTime.Now.ToLongTimeString());
}
my Hub class:
public class EventHub: Hub
{
public void Send(string message)
{
Clients.All.broadcastMessage( message);
}
}
Javascript:
$(function () {
var context = $.connection.eventHub;
context.client.broadcastMessage = function (message) {
alert("clock: " + message);
};
$.connection.hub.start();
});
no error, but no thing occurs on running application. what's my wrong?

context.Clients.All.Send(DateTime.Now.ToLongTimeString());
This will fire a method Send on the clients, it will not call
public void Send(string message)
{
Clients.All.broadcastMessage( message);
}

Related

GUI updates only after the worker thread has ended

I have a Windows Form application and managed DLL in one solution. DLL contains some time consuming functions during which I wish to update the Form contents (callback from the DLL to the Form with progess updates). I have the following code:
Form code, where I initialize the DLL and give it a callback function in the Initialize method. I also start a separate Thread to periodicly check the message_queue for new messages from the DLL. The DLL function is also called in a separate Thread (non blocking for the UI).
private LibraryDLL library_dll;
private ConcurrentQueue<string> message_queue;
public MainForm()
{
InitializeComponent();
library_dll = new LibraryDLL();
message_queue = new ConcurrentQueue<string>();
library_dll.Initialize(ProcessMessage);
new Thread(() =>
{
Thread.CurrentThread.IsBackground = true;
string message;
if (message_queue.TryDequeue(out message))
{
PrintMessage(message);
}
}).Start();
}
private void ProcessMessage(string message)
{
message_queue.Enqueue(message);
}
private void PrintMessage(string message)
{
this.Invoke((MethodInvoker)delegate
{
listBox_rows.Items.Add(message);
});
}
private void button_send_Click(object sender, EventArgs e)
{
new Thread(() =>
{
Thread.CurrentThread.IsBackground = true;
library_dll.DoWork();
}).Start();
}
In DLL code, I use the callback method to report progress:
private CallBack callback;
public delegate void CallBack(string message);
public LibraryDLL() { }
public void Initialize(CallBack callback)
{
this.callback = callback;
}
public void DoWork()
{
callback("working...")
Thread.Sleep(500);
callback("working...")
Thread.Sleep(500);
callback("working...")
Thread.Sleep(500);
}
My problem is, that instead of string "working" appearing every 500ms, it appears 3 times after 1500ms (only after the Thread in which the DoWork method is running ends). I also tried the Invalidate()-Update()-Refresh() sequence in the Form's PrintMessage function, but without any effect.
Thanks for the advice!
EDIT1:
I modified the code to use the BackgroundWorker, however, the problem remains (nothing for 1500ms, than all 3 strings at once).
BackgroundWorker bck_worker;
public MainForm()
{
InitializeComponent();
library_dll = new LibraryDLL();
library_dll.Initialize(bck_worker);
bck_worker = new BackgroundWorker();
bck_worker.ProgressChanged += new ProgressChangedEventHandler(bckWorker_ProgressChanged);
bck_worker.WorkerReportsProgress = true;
bck_worker.WorkerSupportsCancellation = true;
}
private void bckWorker_DoWork(object sender, DoWorkEventArgs e)
{
library_dll.DoWork();
}
private void bckWorker_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
PrintMessage((string)e.UserState);
}
private void button_send_Click(object sender, EventArgs e)
{
bck_worker.DoWork += new DoWorkEventHandler(bckWorker_DoWork);
bck_worker.RunWorkerAsync();
}
private void PrintMessage(string message)
{
listBox_rows.Items.Add(message);
}
And the DLL:
private BackgroundWorker bck_worker;
public LibraryDLL() { }
public void Initialize(BackgroundWorker bck_worker)
{
this.bck_worker = bck_worker;
}
public void DoWork()
{
bck_worker.ReportProgress(25, "working...");
Thread.Sleep(500);
bck_worker.ReportProgress(50, "working...");
Thread.Sleep(500);
bck_worker.ReportProgress(75, "working...");
Thread.Sleep(500);
}
EDIT2:
OK, I now tried to add the Invalidate-Update-Refresh sequence at the end of the PrintMessage function and it finaly works (with the BackgroundWorker approach)!
Use background worker and workers's report progress to update your UI: background worker doc

Starting Help First Android app with c#

I'm trying to write an android app using VS Community 2015 in c#
The App should send a message to a websocket an display it received answer.
This is my MainActivity.cs
public class MainActivity : Activity
{
protected override void OnCreate(Bundle bundle)
{
base.OnCreate(bundle);
// Set our view from the "main" layout resource
SetContentView(Resource.Layout.Main);
// Get our button from the layout resource,
// and attach an event to it
Button button = FindViewById<Button>(Resource.Id.MyButton);
TextView t1 = FindViewById<TextView>(Resource.Id.textView1);
button.Click += delegate
{
string msg = SetStatusText();
t1.SetText(msg,TextView.BufferType.Normal);
};
}
private string SetStatusText()
{
Connector c = new Connector();
c.Connect();
return c.msg;
}
}
The Connector goes like this
class Connector
{
public string msg { get; set; }
WebSocket websocket = new WebSocket("ws://192.168.1.103:2012/");
public void Connect()
{
websocket.Opened += new EventHandler(websocket_Opened);
websocket.MessageReceived += new EventHandler<MessageReceivedEventArgs>(websocket_MessageReceived);
websocket.Open();
}
private void websocket_MessageReceived(object sender, MessageReceivedEventArgs e)
{
msg = e.Message;
}
private void websocket_Opened(object sender, EventArgs e)
{
websocket.Send("Status");
}
}
In debug mode I see the message the websocket returned in msg variable of the Connector, but the way I'm returning it to the MainActivity doesn't work. It stays NULL.
You are using the "msg" variable just after connecting to the WebSocket, that will fail as you still did not received a message, you need to wait in some way to websocket_MessageReceived be executed.
If you want to wait until the message is received you can use an event:
class Connector
{
public string msg { get; set; }
public event EventHandler MessageReceived;
WebSocket websocket = new WebSocket("ws://192.168.1.103:2012/");
public void Connect()
{
websocket.Opened += new EventHandler(websocket_Opened);
websocket.MessageReceived += new EventHandler<MessageReceivedEventArgs>(websocket_MessageReceived);
websocket.Open();
}
private void websocket_MessageReceived(object sender, MessageReceivedEventArgs e)
{
msg = e.Message;
if(MessageReceived != null)
MessageReceived(this, EventArgs.Empty);
}
private void websocket_Opened(object sender, EventArgs e)
{
websocket.Send("Status");
}
}
Then, when you create your connection you can do:
c.MessageReceived += (o,e) => t1.SetText(c.msg,TextView.BufferType.Normal);

How to use subscribe(client) / invoke(server) delegates over network? C#

I must implement an asynchronous communication between client and server, I made a test application that does it through delegates (where the client subscribes to server’s instantiated delegate, that invokes every x seconds). Server and client are running on the same solution, and now I want to put the server on a VM and keep the communication. Is it doable through Delegates? If so, how?
Delegate:
public delegate void ClientStartedEventHandler(String s);
Client:
private void OnStartClick(object sender, EventArgs e)
{
Server.ClientStarted += ClientStarted;
Server.start();
}
private void ClientStarted(String s)
{
MessageBox.Show(s);
}
Server:
public static class Server
{
public static event ClientStartedEventHandler ClientStarted;
public static void start()
{
Timer myTimer = new System.Timers.Timer();
myTimer.Elapsed += new ElapsedEventHandler(exe);
myTimer.Interval = 2000;
myTimer.Enabled = true;
}
private static void exe(object source, ElapsedEventArgs e)
{
String strNow = DateTime.Now.ToString();
if (ClientStarted != null)
{
ClientStarted.Invoke(strNow);
}
}
}

Window service : How to start a Timer at Particular Time

I have seen similar post of setting Timer at particular time ... I Dont want to run timer Whole Day ...I Want to start it at specific Time ..
Most of the suggestion is use Scheduled tasks ...but I want to do it with window service ....
Here is My Service Working Code :
public AutoSMSService2()
{
InitializeComponent();
if (!System.Diagnostics.EventLog.SourceExists("MySource"))
{
System.Diagnostics.EventLog.CreateEventSource(
"MySource", "MyNewLog");
}
eventLog1.Source = "MySource";
eventLog1.Log = "MyNewLog";
Timer checkForTime = new Timer(5000);
checkForTime.Elapsed += new ElapsedEventHandler(checkForTime_Elapsed);
checkForTime.Enabled = true;
}
protected override void OnStart(string[] args)
{
eventLog1.WriteEntry("In OnStart");
}
protected override void OnStop()
{
eventLog1.WriteEntry("In onStop.");
}
void checkForTime_Elapsed(object sender, ElapsedEventArgs e)
{
eventLog1.WriteEntry("Timer Entry");
}
My Timer is working fine and adding Log at 5 sec interval ..But I want to start Timer Lets Say 3:00 PM ...
private static void SetTimer(Timer timer, DateTime due)
{
var ts = due - DateTime.Now;
timer.Interval = ts.TotalMilliseconds;
timer.AutoReset = false;
timer.Start();
}
But I am not sure How to Implement it in Code ..
Any suggestion would be Helpful
If you want to do it every day, Hope this will help.
private System.Threading.Timer myTimer;
private void SetTimerValue ()
{
DateTime requiredTime = DateTime.Today.AddHours(15).AddMinutes(00);
if (DateTime.Now > requiredTime)
{
requiredTime = requiredTime.AddDays(1);
}
myTimer = new System.Threading.Timer(new TimerCallback(TimerAction));
myTimer.Change((int)(requiredTime - DateTime.Now).TotalMilliseconds, Timeout.Infinite);
}
private void TimerAction(object e)
{
//here you can start your timer!!
}
here an example with windows form but you can achieve the some thing with windows service
public partial class Form1 : Form
{
private bool _timerCorrectionDone = false;
private int _normalInterval = 5000;
public Form1()
{
InitializeComponent();
//here you calculate the second that should elapsed
var now = new TimeSpan(0,DateTime.Now.Minute, DateTime.Now.Second);
int corrTo5MinutesUpper = (now.Minutes/5)*5;
if (now.Minutes%5>0)
{
corrTo5MinutesUpper = corrTo5MinutesUpper + 5;
}
var upperBound = new TimeSpan(0,corrTo5MinutesUpper, 60-now.Seconds);
var correcFirstStart = (upperBound - now);
timer1.Interval = (int)correcFirstStart.TotalMilliseconds;
timer1.Start();
}
private void timer1_Tick(object sender, EventArgs e)
{
// just do a correction like this
if (!_timerCorrectionDone)
{
timer1.Interval = _normalInterval;
_timerCorrectionDone = true;
}
}

Windows Store Application Metronome Stop Button Not Working

Hello there i am developing Windows Store App.
First of all, here is my code:
public class TickArgs : EventArgs
{
public DateTime Time { get; set; }
}
public class Metronome
{
private DispatcherTimer _timer;
public event TickHandler Tick;
public delegate void TickHandler(Metronome m, TickArgs e);
public Metronome()
{
_timer = new DispatcherTimer();
_timer.Tick += Timer_Tick;
}
private void Timer_Tick(object sender, object e)
{
if (Tick != null)
{
Tick(this, new TickArgs { Time = DateTime.Now });
}
}
public void Start(int bbm)
{
_timer.Stop();
_timer.Interval = TimeSpan.FromSeconds(60 / bbm);
_timer.Start();
}
public void Stop()
{
_timer.Stop();
_timer.Start();
}
}
public class Listener
{
public void Subscribe(Metronome m, MediaElement mmx)
{
m.Tick += (mm, e) => mmx.Play();
}
public void UnSubscribe(Metronome m, MediaElement mmx)
{
m.Tick += (mm, e) => mmx.Stop();
}
}
To start metronome i use these codes:
l.Subscribe(m, mediaelement);
m.Start(120);
This works perfectly fine.
To stop metronome i use these codes:
l.UnSubscribe(m, mediaelement);
m.Stop();
Metronome stops BUT if i try to start again, it just does not start. What should i do?
I would appreciate your helps.
My regards...
Okay, so what you have done is you've subscribed your metronome to two handlers, each happening on the tick timer.
First of all, make a static method in your Listener class as the event handler that you can remove.
private static void TickPlay(object sender, EventArgs e)
{
mmx.Play();
}
Then, in your Subscribe method, just say:
m.Tick += TickPlay;
Lastly, for your Unsubscribe method, say:
m.Tick -= TickPlay;
This way it won't keep going Play/Stop ever tick interval.
I found the solution.
I've just made small changes in start and stop methods:
public void Start(int bbm)
{
_timer.Interval = new TimeSpan(0, 0, 0, 0, 500);
_timer.Start();
}
public void Stop()
{
_timer.Stop();
}
Now it works perfectly fine.
Regards

Categories

Resources