I am first time working with both windows service and MSMQ. I am trying to read messages from queue. When I start my windows service, i am receiving only first message and next message not able to read, service is still running. if I restart the service It is reading first message from the queue. Please let me know how to fix this issue.
This is my code on start of my service:
protected override void OnStart(string[] args)
{
MessageQueue msMq = null;
JobModel j = new JobModel();
msMq = new MessageQueue(queueRequestName);
try
{
if (msMq != null)
{
msMq.Formatter = new XmlMessageFormatter(new Type[] { typeof(JobModel) });
var message = (JobModel)msMq.BeginReceive();
}
}
catch (MessageQueueException ee)
{
Console.Write(ee.ToString());
}
catch (Exception eee)
{
Console.Write(eee.ToString());
}
finally
{
msMq.Close();
}
}
Just a guess, but I think you shouldn't close the queue:
//keep your queue object in the service scope
//you might need more
MessageQueue msMq = null;
protected override void OnStart(string[] args)
{
JobModel j = new JobModel();
msMq = new MessageQueue(queueRequestName);
try
{
if (msMq != null)
{
msMq.Formatter = new XmlMessageFormatter(new Type[] { typeof(JobModel) });
var message = (JobModel)msMq.BeginReceive();
}
}
catch (MessageQueueException ee)
{
Console.Write(ee.ToString());
}
catch (Exception eee)
{
Console.Write(eee.ToString());
}
}
//close when you stop
protected override OnStop() //signature might be differnt
{
msMq.Close();
}
Have you tried adding an event handler and attaching it to the ReceiveCompleted event, as shown in MessageQueue.BeginReceive?
protected override void OnStart(string[] args)
{
MessageQueue msMq = null;
JobModel j = new JobModel();
msMq = new MessageQueue(queueRequestName);
msMq.ReceiveCompleted += ReceiveCompletedEventHandler(MyMsMqEventHandler)
try
{
if (msMq != null)
{
msMq.Formatter = new XmlMessageFormatter(new Type[] { typeof(JobModel) });
var message = (JobModel)msMq.BeginReceive();
}
}
catch (MessageQueueException ee)
{
Console.Write(ee.ToString());
}
catch (Exception eee)
{
Console.Write(eee.ToString());
}
}
public static void MyMsMqEventHandler(object src, ReceiveCompletedEventHandler handler)
{
var msMq = (MessageQueue)src;
var msg = msMq.EndReceive(handler.AsyncResult);
Console.WriteLine((string)msMq.Body);
msMq.BeginReceive();
}
Related
I have a WCF service as an OPC client that interfaces with an OPC DA server, also I have a WCF client that interacts with WCF and launches it (uses its methods)
The problem is that:
When I use WCF method connectToOPC() at first time, the connection can be break after few seconds, or not. DataChange stops coming.
But when I restart connectToOPC, the connection remains active and does not fall. What happens and why?
WCF Service:
public void connectToOPC(string OPCUrl, int GroupUpdateTime)
{
try
{
Main(OPCUrl, GroupUpdateTime);
}
catch (Exception ex) { Log(ex.Message, ""); }
}
public bool Run(string OPCUrl, int GroupUpdateTime)
{
try
{
url = new Opc.URL(OPCUrl);
server.Connect(url, new Opc.ConnectData(new System.Net.NetworkCredential()));
groupState = new Opc.Da.SubscriptionState();
groupState.Name = "MyGroup";
groupState.UpdateRate = GroupUpdateTime;
groupState.Active = true;
groupRead = (Opc.Da.Subscription)server.CreateSubscription(groupState);
groupRead.DataChanged += new Opc.Da.DataChangedEventHandler(group_DataChanged);
items = new Opc.Da.Item[ListOfTags.Count];
for (int i = 0; i < ListOfTags.Count; i++)
{
items[i] = new Opc.Da.Item();
items[i].ItemName = ListOfTags[i];
}
items = groupRead.AddItems(items);
}
catch (Exception ex)
{
Log(ex.Message, "");
return false;
}
return true;
}
void group_DataChanged(object subscriptionHandle, object requestHandle,Opc.Da.ItemValueResult[] values)
{
//its stops here at first time
}
And code of WCF client(WPF):
public partial class MainWindow : Window
{
OPCClient client;
public MainWindow()
{
InitializeComponent();
client = new OPCClient("BasicHttpBinding_IOPC");
}
private void buttonOpcRun_Click(object sender, RoutedEventArgs e)
{
try
{
GroupUpdateTime = Convert.ToInt32(textBoxUpdateGroupTime.Text);
client.connectToOPC(OPCUrl, GroupUpdateTime);
}
catch (Exception ex)
{
System.Windows.MessageBox.Show(ex + "");
}
}
}
I am trying to use web socket with my bot to communicate with the server. But on run time it throws the System.NullReferenceException. I am running socket in background on a different thread so that it does not interfear with the bot.
I am using WebsocketSharp library.
First message comes in just fine but on second message it throws exception at following line in HumanCollaboratorDialog class.
await context.PostAsync(e.Data);
My Socket Stream Class is as following:
public static class SocketStream
{
public static WebSocket ws;
private static List<string> serverMsg = new List<string>();
public static void initializeSocket()
{
ws = new WebSocket("ws://Some IP:8080/human-collaborator/data");
Debug.WriteLine("****** INITIALIZED SOCKET (should happen only once) *****");
Task.Run(() => startSocketStream());
}
private static void startSocketStream()
{
int attempts = 0;
while (!ws.IsAlive)
{
try
{
attempts++;
ws.Connect();
}
catch (WebSocketException)
{
Debug.WriteLine("Connection attempts: " + attempts.ToString());
}
}
ws.OnOpen += (sender, args) =>
{
Debug.WriteLine("# SOCKET OPENED");
};
ws.OnError += (sender, args) =>
{
Debug.WriteLine("# SOME ERROR OCCURED");
};
ws.OnClose += (sender, args) =>
{
Debug.WriteLine("# SOCKET CLOSED");
};
}
}
I am calling the initializeSocket() method in Global.asx to run it on application level
public class WebApiApplication : System.Web.HttpApplication
{
protected void Application_Start()
{
GlobalConfiguration.Configure(WebApiConfig.Register);
SocketStream.initializeSocket();
}
}
My HumanCollaboratorDialog class is as following:
[Serializable]
public class HumanCollaboratorDialog : IDialog<object>
{
public async Task StartAsync(IDialogContext context)
{
context.Wait(this.MessageReceivedAsync);
}
private async Task MessageReceivedAsync(IDialogContext context, IAwaitable<IMessageActivity> result)
{
var message = await result;
SocketStream.ws.OnMessage += async (sender, e) =>
{
try
{
await context.PostAsync(e.Data);
}
catch (HttpRequestException ex)
{
throw ex;
}
};
Thread.Sleep(500);
string output = message.Text;
SocketStream.ws.Send(output);
Thread.Sleep(500);
context.Wait(MessageReceivedAsync);
}
}
My MessagesController has following POST method:
public virtual async Task<HttpResponseMessage> Post([FromBody]Activity activity)
{
if (activity.Type == ActivityTypes.Message)
{
await Conversation.SendAsync(activity, () => new HumanCollaboratorDialog());
}
else
{
HandleSystemMessage(activity);
}
var response = Request.CreateResponse(HttpStatusCode.OK);
return response;
}
Neithet e.Data nor context is empty. I think problem is with socket connection or may be i am doing something wrong in SocketStream class. following is the image
Your bot is a web service. Messages are sent to the service by the client (a web page, an application, another service, etc.) and received in the MessagesController's Post method. There's no need to have the socket code on the server for what you're trying to do. Web Sockets are useful for receiving messages on a client from the bot via a Direct Line connection.
Here is an example of using the Bot Framework's Direct Line Client and creating a web socket connection. Notice how the web socket is created from a conversation's StreamUrl:
DirectLineClientCredentials creds = new DirectLineClientCredentials(directLineSecret);
DirectLineClient directLineClient = new DirectLineClient(creds);
Conversation conversation = await directLineClient.Conversations.StartConversationAsync();
using (var webSocketClient = new WebSocket(conversation.StreamUrl))
{
webSocketClient.OnMessage += WebSocketClient_OnMessage;
webSocketClient.Connect();
while (true)
{
string input = Console.ReadLine().Trim();
if (input.ToLower() == "exit")
{
break;
}
else
{
if (input.Length > 0)
{
Activity userMessage = new Activity
{
From = new ChannelAccount(fromUser),
Text = input,
Type = ActivityTypes.Message
};
await directLineClient.Conversations.PostActivityAsync(conversation.ConversationId, userMessage);
}
}
}
}
private static void WebSocketClient_OnMessage(object sender, MessageEventArgs e)
{
// avoid null reference exception when no data received
if (string.IsNullOrWhiteSpace(e.Data))
{
return;
}
var activitySet = JsonConvert.DeserializeObject<ActivitySet>(e.Data);
var activities = from x in activitySet.Activities
where x.From.Id == botId
select x;
foreach (Activity activity in activities)
{
Console.WriteLine(activity.Text);
}
}
This is from a console application that is using the Direct Line to communicate with the Bot and is listening for messages using web sockets here:
https://github.com/Microsoft/BotBuilder-Samples/tree/master/CSharp/core-DirectLineWebSockets
So my service is a simple chat application between two wcf clients. Event callback works when I call events. After I close my client and run it again, and write a message again (to call the event) it throws me exception:
An exception of type 'System.ObjectDisposedException' occurred in
RussianRouletteServiceLibrary.dll but was not handled in user code
Additional information: Cannot access a disposed object.
The code for my service callback is as follows:
private static Action<User, UMessage> gameChat = delegate { };
public void Play()
{
IGameCallback subscriber =
OperationContext.Current.GetCallbackChannel<IGameCallback>();
gameChat += subscriber.PlayerSentMessage;
}
This is the event trigger:
public void SendMessage(User user, UMessage message)
{
try
{
gameChat(user, message);
}
catch (Exception ex)
{
throw ex;
}
}
I get this error every time I .ChannelFactory.Close(); .Close(); the client while closing form event is happening.
Is there anyone that knows how to fix this and is willing to share his knowledge?
Thank you in advance!
EDIT #1
This is the code of the client when it opens:
ConcurrencyMode.Multiple,
UseSynchronizationContext = false)]
public partial class GameForm : Form, IGameCallback
{
#region IGame Callbacks
public void PlayerSentMessage(User user, UMessage message)
{
string nickname = user.NickName == clientUser.NickName ? "You" : user.NickName;
this.Invoke(new MethodInvoker(() => lb_ChatBox.Items.Add(nickname + " : " + message.MessageContent)));
}
#endregion
private GameClient _gameClient = null;
private InstanceContext _instance = null;
private User clientUser = new User(){ Email = "zigm4s#gmail.com", Id = 0, FirstName = "Zigmas", LastName = "Slusnys", NickName = "Ziggy", Password = "test123"};
public GameForm()
{
string state;
if (_gameClient != null)
{
MessageBox.Show("nelygu null");
MessageBox.Show(_gameClient.State.ToString());
//_gameClient = new GameClient(new InstanceContext(this));
}
else
{
_gameClient = new GameClient(new InstanceContext(this));
MessageBox.Show(_gameClient.State.ToString());
}
InitializeComponent();
try
{
_gameClient.Open();
_gameClient.Play();
}
catch (Exception ex)
{
MessageBox.Show(ex.ToString());
}
}
This is when the client form is closing.
private void GameForm_FormClosing(object sender, FormClosingEventArgs e)
{
try {
if (_gameClient.State != System.ServiceModel.CommunicationState.Faulted)
{
MessageBox.Show("Closing client");
_gameClient.ChannelFactory.Close();
_gameClient.Close();
}
else
{
MessageBox.Show("Aborting client");
_gameClient.Abort();
}
}
catch(Exception ex)
{ MessageBox.Show(ex.ToString());}
}
EDIT #2
I found the mistake, on the service side i had delegates that were static. It doesn't throw this error when it's not static.
I have created a application to send messages between client-server and I am having a
problem on server side.
I want to write the incoming NewOrderSingle message( .body extension file) files in store folder on server side.
The newordersingle message along with executionreport message get written into store file on client side. but on server side I don’t get application messages(file with .body extension) in store file.
How to write the incoming application messages to the file and not the admin messages.
My sample code is as follows:
public class clsFIXServer : QuickFix.MessageCracker, QuickFix.IApplication
{
public void FromApp(QuickFix.Message message, QuickFix.SessionID sessionID)
{
Console.WriteLine("IN: " + message);
Crack(message, sessionID);
}
public void OnCreate(QuickFix.SessionID sessionID)
{
}
public void OnLogon(QuickFix.SessionID sessionID)
{
}
public void OnLogout(QuickFix.SessionID sessionID)
{
}
public void ToAdmin(QuickFix.Message message, QuickFix.SessionID sessionID)
{
}
public void ToApp(QuickFix.Message message, QuickFix.SessionID sessionId)
{
Console.WriteLine("OUT: " + message);
}
public void OnMessage(QuickFix.FIX44.NewOrderSingle n, SessionID s)
{
Symbol symbol = n.Symbol;
Side side = n.Side;
OrdType ordType = n.OrdType;
OrderQty orderQty = n.OrderQty;
Price price = new Price(DEFAULT_MARKET_PRICE);
ClOrdID clOrdID = n.ClOrdID;
switch (ordType.getValue())
{
case OrdType.LIMIT:
price = n.Price;
if (price.Obj == 0)
throw new IncorrectTagValue(price.Tag);
break;
case OrdType.MARKET: break;
default: throw new IncorrectTagValue(ordType.Tag);
}
QuickFix.FIX44.ExecutionReport exReport = new QuickFix.FIX44.ExecutionReport(
new OrderID(GenOrderID()),
new ExecID(GenExecID()),
new ExecType(ExecType.FILL),
new OrdStatus(OrdStatus.FILLED),
symbol, //shouldn't be here?
side,
new LeavesQty(0),
new CumQty(orderQty.getValue()),
new AvgPx(price.getValue()));
exReport.Set(clOrdID);
exReport.Set(symbol);
exReport.Set(orderQty);
exReport.Set(new LastQty(orderQty.getValue()));
exReport.Set(new LastPx(price.getValue()));
if (n.IsSetAccount())
exReport.SetField(n.Account);
try
{
Session.SendToTarget(exReport, s);
}
catch (SessionNotFound ex)
{
Console.WriteLine("==session not found exception!==");
Console.WriteLine(ex.ToString());
}
catch (Exception ex)
{
Console.WriteLine(ex.ToString());
}
}
}
My client side function that creates the newordersingle message :-
public void Run()
{
objEMSOrder = ((FIXFormatter.EMSOrder)messageQueue.Receive().Body);
if (this._session.SessionID.BeginString == "FIX.4.4")
{
QuickFix.FIX44.NewOrderSingle m = objMessageCreator.NewOrderSingle44MessageCreator(objEMSOrder);
**//DLL FUNCTION THAT CREATES MESSAGE**
if (m != null)
{
m.Header.GetField(Tags.BeginString);
SendMessage(m);
}
}
}
The message store is for internal use by the FIX session protocol. It only stores outgoing messages so that if there is a sequence gap is can resend previously sent messages. You want to look at the FileLogFactory and FileLog classes. Those will log both incoming and outgoing messages.
I wet through this except that I added it to a windows service like this
public partial class TriggerHostProcesses : ServiceBase
{
private const string MESSAGE_QUEUE = #".\Private$\Sample Queue";
private MessageQueue _queue;
public TriggerHostProcesses()
{
InitializeComponent();
}
protected override void OnStart(string[] args)
{
SendMessage("Hope This Works");
}
protected override void OnStop()
{
}
internal void start()
{
OnStart(null);
}
private void SendMessage(string message)
{
_queue = new MessageQueue(MESSAGE_QUEUE);
Message msg = new Message();
msg.Body = message;
msg.Label = "Testing " + DateTime.Now.ToString();
_queue.Send(msg,new MessageQueueTransaction());
}
}
and to get the message
partial class HostListener : ServiceBase
{
private const string MESSAGE_QUEUE = #".\Private$\Sample Queue";
private MessageQueue _queue;
public HostListener()
{
InitializeComponent();
}
protected override void OnStart(string[] args)
{
try
{
var myTransaction = new MessageQueueTransaction();
var queue = new MessageQueue(MESSAGE_QUEUE);
var message = queue.Receive(new TimeSpan(0, 0, 20),myTransaction);
message.Formatter = new XmlMessageFormatter(
new String[] { "System.String,mscorlib" });
Console.WriteLine(message.Body.ToString());
}
catch(Exception ex)
{
Console.WriteLine("No Message");
}
}
protected override void OnStop()
{
// TODO: Add code here to perform any tear-down necessary to stop your service.
}
internal void start()
{
OnStart(null);
}
}
in my main I added this
var ServiceToRun1 = new TriggerHostProcesses();
var ServiceToRun2 = new HostListener();
if (Environment.UserInteractive)
{
// This used to run the service as a console (development phase only)
ServiceToRun1.start();
ServiceToRun2.start();
Console.WriteLine("Press Enter to terminate ...");
Console.ReadLine();
ServiceToRun1.Stop();
ServiceToRun2.Stop();
}
else
{
ServiceBase.Run(ServiceToRun1);
}
I get the exception Timeout for the requested operation has expired.
Can someone please check if they can see what the problem is?
I don't believe you are using transactions correctly. For example, when sending a message you use:
_queue.Send(msg,new MessageQueueTransaction());
However, this does not begin or commit a transaction. Looking in MSDN the example uses the following code (edited by me):
var myTransaction = new MessageQueueTransaction();
myTransaction.Begin();
myQueue.Send("hello world", myTransaction);
myTransaction.Commit();
I don't believe your message is getting sent, and so your Receive times out.
Similarly your receive logic doesn't seem to correctly use transactions:
myTransaction.Begin();
var myMessage = myQueue.Receive(myTransaction);
var body myOrder = (string)myMessage.Body;
myTransaction.Commit();
You should Rollback in the event of an exception processing your messages so they can be placed back on the queue.
Here is my final product. I'm using this in a windows service. 20 s at a time to see if I have a message then do my processes.
public class MSMQueue:IQueue
{
public MSMQueue(string queueName)
{
Message_Queue = queueName;
}
public string Message_Queue { get; private set; }
public string Pop()
{
MessageQueue queue = new MessageQueue(Message_Queue);
if (queue.Transactional)
return popTransactionalQueue(queue, new TimeSpan(0, 0, 1));
else
return popNormalQueue(queue, new TimeSpan(0, 0, 1));
}
public string Pop(TimeSpan timeSpan)
{
MessageQueue myQueue = new MessageQueue(Message_Queue);
if (myQueue.Transactional)
return popTransactionalQueue(myQueue, timeSpan);
else
return popNormalQueue(myQueue, timeSpan);
}
public void Add(string message)
{
// Connect to a queue on the local computer.
MessageQueue myQueue = new MessageQueue(Message_Queue);
// Send a message to the queue.
if (myQueue.Transactional)
{
var myTransaction = new MessageQueueTransaction();
myTransaction.Begin();
myQueue.Send(message, myTransaction);
myTransaction.Commit();
}
else
myQueue.Send(message);
}
#region private methods
private string popNormalQueue(MessageQueue queue, TimeSpan timeOut)
{
var message = queue.Receive(timeOut);
message.Formatter = new XmlMessageFormatter(
new String[] { "System.String,mscorlib" });
return message.Body.ToString();
}
private string popTransactionalQueue(MessageQueue queue, TimeSpan timeOut)
{
// Set the formatter.
queue.Formatter = new XmlMessageFormatter(new Type[]
{typeof(String)});
// Create a transaction.
MessageQueueTransaction myTransaction = new
MessageQueueTransaction();
String message=string.Empty;
try
{
myTransaction.Begin();
Message myMessage = queue.Receive(timeOut, myTransaction);
message = (String)myMessage.Body;
myTransaction.Commit();
}
catch (MessageQueueException e)
{
myTransaction.Abort();
throw e;
}
return message;
}
#endregion
}