I am using background worker in my Application
my code for this
void CreateThreadForEachServer()
{
DataAccess oDA = new DataAccess();
List<Server> allServerData = oDA.GetAllServers();
foreach (Server serverData in allServerData)
{
backgroundWorker = new BackgroundWorker();
backgroundWorker.DoWork += new DoWorkEventHandler(backgroundWorker_DoWork);
backgroundWorker.RunWorkerAsync(serverData);
}
}
void backgroundWorker_DoWork(object sender, DoWorkEventArgs e)
{
Server server = (Server)e.Argument;
CreateSnapshotForEachServer(server);
}
void CreateSnapshotForEachServer(Server server)
{
DataAccess oDA = new DataAccess();
MsmqMessageFormat message = new MsmqMessageFormat();
try
{
message = new Queue().ReadMessageFromMSMQ(server.ServerName);
}
catch
{
}
}
My problem is when I am calling this method
try
{
message = new Queue().ReadMessageFromMSMQ(server.ServerName);
}
catch
{
}
in a background worker then i can not able to call this method just read a message from MSMQ
But when i can't use background worker just call this method in simple thread like this
void CreateThreadForEachServer()
{
DataAccess oDA = new DataAccess();
List<Server> allServerData = oDA.GetAllServers();
foreach (Server serverData in allServerData)
{
ThreadStart t = delegate { CreateSnapshotForEachServer(serverData); };
Thread td = new Thread(t);
td.Priority = ThreadPriority.Highest;
td.Start();
}
}
then this method call properly
try
{
message = new Queue().ReadMessageFromMSMQ(server.ServerName);
}
catch
{
}
what is the problem with background worker my Queue class is like this
class Queue
{
public MsmqMessageFormat ReadMessageFromMSMQ(string queueName)
{
MessageQueue messageQueue = null;
messageQueue = new MessageQueue(#".\Private$\" + queueName);
messageQueue.Formatter = new XmlMessageFormatter(new Type[] { typeof(MsmqMessageFormat) });
System.Messaging.Message msg = null;
System.Messaging.Message[] allMessages = messageQueue.GetAllMessages();
if (allMessages.Length > 0)
{
msg = messageQueue.Receive();
MsmqMessageFormat readMessage = (MsmqMessageFormat)(msg.Body);
return readMessage;
}
else
{
return null;
}
}
}
and MsmqMessageFormat class is like this
[Serializable]
public class MsmqMessageFormat
{
public Zvol Zvol { get; set;}
public List<PolicyInterval> listPolicyIntervalInfo = new List<PolicyInterval>();
}
Can you clarify on the context of your application?
Is it a Windows Forms app? Console app? Or WPF?
It could have something to do with the apartmentstate of the thread. Threads used by the BackgroundWorker are defaulted to MTA (and you can't override it). While threads created manually could have there apartmentstate set to STA.
I'm not sure about your approach is correct.. I would read messages one by one and bind the appropriate events.
From the link:
The Message Loop
The final line in the example above
was "queue.BeginReceive()". This is a
critical line to a successful
implementation of Microsoft Message
Queue in that it provides the means
for continuous listening on the
message queue. Each time a message is
received, the listening process stops.
This helps provide a thread-safe
environment. However, it also means
it's the developer's responsibility to
resume listening to the queue.
Using the Microsoft Message Queue MSMQ and C#
Also in the last bit of code you have in your question:
if (allMessages.Length > 0)
{
msg = messageQueue.Receive();
MsmqMessageFormat readMessage = (MsmqMessageFormat)(msg.Body);
return readMessage;
}
else
{
return null;
}
This will get all messages and consume them, but will only return the first message even if there are more than one in the queue.
Related
I'm developing an application in C # on WPF.
I need to launch more than once the same MyListWindow class which consists of XAML and the code behind XAML.CS.
The problem is that strange things happen (from my point of view and because of my ignorance).
In particular, I have a main thread that launches a PIPE Server which should launch multiple secondary threads, each of which instantiates a new MyListWindow window.
Strange things happen just when more than one secondary thread is launched from the main thread. First of all he throws me an exception which warns me that the MyListWindow object is already in use by another thread, but it does not make sense, because each secondary thread invokes a new one.
Part of the code is posted below:
namespace Kyactus
{
public partial class App
{
private Registration _reg = new Registration();
public App()
{
if (Process.GetProcessesByName(Path.GetFileNameWithoutExtension(Assembly.GetEntryAssembly().Location)).Count() > 1)
{
Process currentProcess = Process.GetCurrentProcess();
if (Environment.GetCommandLineArgs().Length != 2)
{
currentProcess.Kill();
return;
}
var client = new NamedPipeClientStream("IPC_Context_Menu");
client.Connect();
var writer = new StreamWriter(client);
writer.WriteLine(Environment.GetCommandLineArgs()[1]);
writer.Flush();
currentProcess.Kill();
}
else
{
Globals.MainWindow = new MainWindow();
Globals.MainWindow.Show();
StartContextMenuListener();
}
}
public void StartContextMenuListener()
{
Thread t = new Thread(myTask);
t.SetApartmentState(ApartmentState.STA);
t.Start();
}
void myTask()
{
NamedPipeServerStream server;
while (true)
{
server = new NamedPipeServerStream("IPC_Context_Menu");
server.WaitForConnection();
var reader = new StreamReader(server);
string FileOrFolderFromContextMenu = reader.ReadLine();
Thread t = new Thread(() =>
{
ListUsersContextMenu listWindow = new ListUsersContextMenu(Globals.MainWindow.UsersXAML.Items, FileOrFolderFromContextMenu);
listWindow.ShowDialog(); // Thorws: System.InvalidOperationException because object 'listWindow' is property of another thread
IList selectedUsers = listWindow.DialogResult();
foreach (User selectedUser in selectedUsers)
{
Client c = new Client();
c.invoke(selectedUser.IP.ToString(), FileOrFolderFromContextMenu, selectedUser.ID, selectedUser.Name);
}
});
t.SetApartmentState(ApartmentState.STA);
t.IsBackground = true;
t.Start();
t.Join();
server.Close();
}
}
}
}
How can I solve this problem? I wish I could run the lambda several times.
I have an issue about the server-client communication.
I googled around but I did not find a solution to this.
Right now I am using 32feet in order to get in touch 2 or more (till 7) BT clients to 1 BT server.
I need to broadcast a message from the server to every device in the same time, but I don't know how to do it.
The only way I figured out was to use the list of connection in order to send the message one per time, but it means a delay between each message sent (around 100 ms per device). Unfortunately it means to have a large delay on the last one.
Can someone please give me an advice on how to solve this problem?
Is there a way to broadcast the message to all devices in the same time?
If it can be helpfull, here there is the handle of connection and reading from devices.
Thanks for your help
private void btnStartServer_Click(object sender, EventArgs e)
{
btnStartClient.Enabled = false;
ConnectAsServer();
}
private void ConnectAsServer()
{
connessioniServer = new List<BluetoothClient>();
// thread handshake
Thread bluetoothConnectionControlThread = new Thread(new ThreadStart(ServerControlThread));
bluetoothConnectionControlThread.IsBackground = true;
bluetoothConnectionControlThread.Start();
// thread connessione
Thread bluetoothServerThread = new Thread(new ThreadStart(ServerConnectThread));
bluetoothServerThread.IsBackground = true;
bluetoothServerThread.Start();
}
private void ServerControlThread()
{
while (true)
{
foreach (BluetoothClient cc in connessioniServer)
{
if (!cc.Connected)
{
connessioniServer.Remove(cc);
break;
}
}
updateConnList();
Thread.Sleep(0);
}
}
Guid mUUID = new Guid("fc5ffc49-00e3-4c8b-9cf1-6b72aad1001a");
private void ServerConnectThread()
{
updateUI("server started");
BluetoothListener blueListener = new BluetoothListener(mUUID);
blueListener.Start();
while (true)
{
BluetoothClient conn = blueListener.AcceptBluetoothClient();
connessioniServer.Add(conn);
Thread appoggio = new Thread(new ParameterizedThreadStart(ThreadAscoltoClient));
appoggio.IsBackground = true;
appoggio.Start(conn);
updateUI(conn.RemoteMachineName+" has connected");
}
}
private void ThreadAscoltoClient(object obj)
{
BluetoothClient clientServer = (BluetoothClient)obj;
Stream streamServer = clientServer.GetStream();
streamServer.ReadTimeout=1000;
while (clientServer.Connected)
{
try
{
int bytesDaLeggere = clientServer.Available;
if (bytesDaLeggere > 0)
{
byte[] bytesLetti = new byte[bytesDaLeggere];
int byteLetti = 0;
while (bytesDaLeggere > 0)
{
int bytesDavveroLetti = streamServer.Read(bytesLetti, byteLetti, bytesDaLeggere);
bytesDaLeggere -= bytesDavveroLetti;
byteLetti += bytesDavveroLetti;
}
updateUI("message sent from "+clientServer.RemoteMachineName+": " + System.Text.Encoding.Default.GetString(bytesLetti));
}
}
catch { }
Thread.Sleep(0);
}
updateUI(clientServer.RemoteMachineName + " has gone");
}
private void updateUI(string message)
{
Func<int> del = delegate()
{
textBox1.AppendText(message + System.Environment.NewLine);
return 0;
};
Invoke(del);
}
private void updateConnList()
{
Func<int> del = delegate()
{
listaSensori.Items.Clear();
foreach (BluetoothClient d in connessioniServer)
{
listaSensori.Items.Add(d.RemoteMachineName);
}
return 0;
};
try
{
Invoke(del);
}
catch { }
}
I don't exactly understand how you do it right now (the italian names are not helping...) but maybe my solution can help you.
first of all, bluetooth classic does not support broadcast. so you have to deliver at one at a time.
i do connect to 7 serial port devices at a time, using 7 threads. then i tell every thread to send data. this is very close to same time, but of course not exactly.
let me know if that helps or if you need a code example.
This have probably been asked before, but I cant find the right answer.
I have a dll that runs a pipe in it's own thread. I use that dll in a Unity project, but the messages I push to Unity end up as exception, due to I don't call them from the main thread. So I need some help implementing this right. Here's how I start the background worker:
var worker = new BackgroundWorker();
worker.DoWork += (sender, e) =>
{
var client = new NamedPipeClientStream(".", "kinect-pipe", PipeDirection.In);
client.Connect();
while (_isWorkerRunning)
{
using (var sr = new StreamReader(client))
{
string temp;
while ((temp = sr.ReadLine()) != null)
{
// TODO send message to Unity in main thread
}
}
if (!client.IsConnected)
{
client.Connect();
}
}
client.Flush();
client.Close();
client.Dispose();
};
worker.RunWorkerAsync();
My pipe client runs in a thread, I have a public event that fires the messages to Unity. But i need to ensure the messages is dispatched. And I am not sure how to do this the right way?
I found a simple solution, where I use a shared buffer across the threads. So my pipe look like this:
private void PipeClientWorker()
{
//Client
var client = new NamedPipeClientStream(".", "kinect-pipe", PipeDirection.In);
client.Connect();
while (_isWorkerRunning)
{
using (var sr = new StreamReader(client))
{
string temp;
while ((temp = sr.ReadLine()) != null)
{
// TODO figure out how to do this in the right thread
if (KinectHandler != null)
{
KinectHandler.BeginInvoke(temp, null, null);
}
}
}
if (!client.IsConnected)
{
client.Connect();
}
}
client.Flush();
client.Close();
}
And I start it normally:
var thread = new Thread(PipeClientWorker) {Name = "Pipe Worker Thread", IsBackground = true};
thread.Start();
In Unity I've created a KinectController that puts the messages in a stack, and in the Update loop pops them to a single LastMessage string:
public string LastMessage;
private KinectReader _kinectReader;
private volatile Stack<string> _messageStack;
// Use this for initialization
void Start ()
{
_messageStack = new Stack<string>();
LastMessage = "";
// init Kinect Reader
_kinectReader = new KinectReader();
_kinectReader.StartPipeReader();
_kinectReader.KinectHandler += _kinectReader_KinectHandler;
}
void _kinectReader_KinectHandler(string message)
{
_messageStack.Push(message);
}
// Update is called once per frame
void Update ()
{
// Update Last message
while (_messageStack.Any())
{
LastMessage = _messageStack.Pop();
Debug.Log(LastMessage);
}
}
void OnApplicationQuit()
{
Debug.Log("Stoping the pipe client");
_kinectReader.Stop();
Debug.Log("Qutting application");
}
If anyone have similar issues or have solved it different I would like to discuss the solution :)
Try Thread Ninja. With it you can run background jobs in a coroutine style.
Trying to convert XML files using XSL and printing the output. However, receiving the following message: The calling thread cannot access this object because a different thread owns it.
To set an interval for checking files, added a timer to the OnStart.
if (findPrinter() > 0)
{
System.Timers.Timer printNetterCheck = new System.Timers.Timer();
printNetterCheck.Elapsed += new ElapsedEventHandler(OnTimedEvent);
printNetterCheck.Interval = 30000;
printNetterCheck.Enabled = true;
}
The OnTimedEvent:
private void OnTimedEvent(object source, ElapsedEventArgs e)
{
getFiles();
}
If any files available, call print:
foreach (string file in files)
{
try
{
StringWriter xslTransformResult = new StringWriter();
XslCompiledTransform xslt = new XslCompiledTransform();
xslt.Load(xslPath);
xslt.Transform(file, null, xslTransformResult);
if (print(xslTransformResult) == 1)
{
//do some things
The print function:
private int print(StringWriter transformedXML)
{
//assume OK
int rc = 1;
try
{
StringReader printNetterStreamReader = new StringReader(transformedXML.ToString());
PrintSystemJobInfo printNetterJob = printer.AddJob("PrintNetterPrint");
Stream printNetterStream = printNetterJob.JobStream;
Byte[] printNetterByteBuffer = UnicodeEncoding.Unicode.GetBytes(printNetterStreamReader.ReadToEnd());
printNetterStream.Write(printNetterByteBuffer, 0, printNetterByteBuffer.Length);
printNetterStream.Close();
}
catch (Exception e)
{
//return fail
rc = -1;
eventLog.WriteEntry("Error printing: " + e.Message, EventLogEntryType.Error);
}
return rc;
}
When calling print I receive the thread error. Found some stuff about Dispatchers etc.. but those are not available when using services.
Check PrintQueue.AddJob.
The method makes a COM call which requires the application be running in a single apartment (STA). The easiest way to fix that is to add STAThreadAttribute to Main which will force the application to run in a single thread. If you need multithreading in your application then you will need to implement the necessary plumbing to run the PrintQueue separately on an STA Thread.
// Create a factory to hold your printer configuration
// So that it can be retrieved on demand
// You might need to move the findPrinter() logic
public class PrintQueueFactory
{
private static PrintQueue _instance = new PrinterQueue(/* Details */);
public static PrintQueue PrintQueue { get { return _instance; } }
}
private int print(StringWriter transformedXML)
{
//assume OK
int rc = 1;
try
{
var printer = PrintQueueFactory.PrintQueue;
var staThread = new Thread(() => Print(printer, transformedXML.ToString()));
staThread.SetApartmentState(ApartmentState.STA);
staThread.Start();
staThread.Join();
}
catch (Exception e)
{
//return fail
rc = -1;
eventLog.WriteEntry("Error printing: " + e.Message, EventLogEntryType.Error);
}
return rc;
}
private static void Print(PrintQueue printer, string lines)
{
using(var printNetterJob = printer.AddJob("PrintNetterPrint"))
using(var printNetterStreamReader = new StringReader(lines))
using(var printNetterStream = printNetterJob.JobStream)
{
Byte[] printNetterByteBuffer = UnicodeEncoding.Unicode.GetBytes(printNetterStreamReader.ReadToEnd());
printNetterStream.Write(printNetterByteBuffer, 0, printNetterByteBuffer.Length);
}
}
maybe, as you are using a Timer control, it is related with multi-threading, maybe you should check if an Invoke is Required (InvokeRequired) in the Timer.Elapsed event handler.
If so, you should create a delegate to call this function, so it can be executed in the right thread.
Check this Invoke-Required question
I am modifying a windows desktop application that works with some external hardware. When the user activates the hardware from the application a progress (UI) form is started. This form creates a thread that performs all of the work with the hardware. The problem comes when I try to report progress back to the UI thread. It appears that the first of my Control.BeginInvoke ("Negotiating message") works fine. However, the second one (first adjustment to progressbar) never seems to call it's delegate and as a result the application locks up on the subsequent endinvoke. I believe the issue is that the GUI is now in an idle state, but I am not sure how to fix the situation. Any help would be appreciated. Code found below:
In the UI Load Method Thread:
private void frmTwainAquire_Load(object sender, EventArgs e)
{
try
{
//Show the GUI
this.Visible = showGUI;
pbScanningProgress.Value = 0;
btnCancel.Enabled = false;
btnCancel.Visible = false;
// Set the delegates.
SetScanMessageDelegate = new SetScanMessage(this.SetScanMessageMethod);
SetRegistrationMessageDelegate = new SetRegistrationMessage(this.SetRegistrationMessageMethod);
AddScanProgressDelegate = new AddScanProgress(this.AddScanProgressMethod);
AddRecogProgressDelegate = new AddRecogProgress(this.AddRecogProgressMethod);
// Set progress bars.
pbScanningProgress.Value = 0;
pbRecognition.Value = 0;
abortScan = false;
// Create thread here!
twainInstance = new rScan.Twain();
rScanning = new rScanThread(this, twainInstance);
// Start the thread.
rScanning.tScan = new Thread(rScanning.Scan);
rScanning.tScan.Start();
}
catch (Exception ex)
{
// Error checking here.
}
}
Delegate Methods:
public void SetScanMessageMethod(string scanMessage)
{
this.lblScanMessage.Text = scanMessage;
}
public void SetRegistrationMessageMethod(string recogMessage)
{
this.lblRecognition.Text = recogMessage;
}
public void AddScanProgressMethod(int progress)
{
this.pbScanningProgress.Value += progress;
}
public void AddRecogProgressMethod(int progress)
{
this.pbRecognition.Value += progress;
}
Thread method that is giving the problem. Please note that the thread is in a different class then the previous two code blocks (both are in the UI class):
public class rScanThread : IMessageFilter
public void Scan()
{
// Set progress bar message.
IAsyncResult result;
if (frmTwainAquireInstance.lblScanMessage.IsHandleCreated && frmTwainAquireInstance.lblScanMessage.InvokeRequired)
{
result = frmTwainAquireInstance.lblScanMessage.BeginInvoke(frmTwainAquireInstance.SetScanMessageDelegate, "Negotiating Capabilities with Scanner.");
frmTwainAquireInstance.lblScanMessage.EndInvoke(result);
}
else
{
frmTwainAquireInstance.lblScanMessage.Text = "Negotiating Capabilities with Scanner.";
}
// Start the intialization of the rScan process.
bool intializeSuccess = twainInstance.Initialize(frmTwainAquireInstance.Handle);
// If the process could not be started then quit.
if (!intializeSuccess)
{
frmTwainAquireInstance.Close();
return;
}
if (frmTwainAquireInstance.pbScanningProgress.IsHandleCreated && frmTwainAquireInstance.pbScanningProgress.InvokeRequired)
{
result = frmTwainAquireInstance.pbScanningProgress.BeginInvoke(frmTwainAquireInstance.AddScanProgressDelegate, 33);
frmTwainAquireInstance.pbScanningProgress.EndInvoke(result); // Lock up here.
}
else
{
frmTwainAquireInstance.pbScanningProgress.Value += 33;
}
// Do more work after. The code never makes it this far.
} // End of rScanThread.Scan()