|
Hi,
Is the result being overwritten with the next string from standard output before the timer driven routine has read it? Why not remove the timer and process the strings as they arrive, e.g.
while (!proc.HasExited)
{
string tekst = proc.StandardOutput.ReadLine();
ProgressUpdate(tekst);
}
Alan.
|
|
|
|
|
You're trying to get the console output generated by an app. There typically can be two output streams, one is the (regular) output stream (stdout in C environment), the other the error stream (stderr in C environment). The former typically is used for regular output, the latter for error reporting (but you can't really tell just by looking at it).
You can easily get both of them asynchronously (i.e. after the process has finished) by using Process.StandardOutput.ReadToEnd() and Process.StandardError.ReadToEnd() .
If you want to get them both while the process is still running, you need more than one thread, as the read calls (like the ReadLine you're using now) are blocking. There are two ways to get there:
1. use 2 threads, each having a loop such as yours;
2. use 2 events: Process.OutputDataReceived and Process.ErrorDataReceived which probably run on ThreadPool threads automatically (cfr this article[^])
wathever choice you make, be careful about thread safety (in a WinForms app your threads or event handlers would not be allowed to touch GUI Controls directly (for more, see rhis article[^])
|
|
|
|
|
Hi All,
I want to merge 2 tables.
These 2 tables have different columns but the no.of records same.
DataTable dt1, DataTable dt2;
dt1: contains records like below
===============================
colA colB colC
----------------
a1 b1 c1
a2 b2 c2
a3 b3 c3
dt2: contains records like below
===============================
colD colE colF
----------------
d1 e1 f1
d2 e2 f2
d3 e3 f3
I have to make these two table into one single table like below
Required DataTable
colA colB colC colD colE colF
--------------------------------
a1 b1 c1 d1 e1 f1
a2 b2 c2 d2 e2 f2
a3 b3 c3 d3 e3 f3
How can we do that?
I approached like, taken a DataTable and added columns of dt1 and dt2 the this table. then added the records to main DataTable through looping each record of dt1 and dt2.
Is there any other way do this with out using loop statements.
Both the tables are different, they don't have any relation between them, only the no.of records were same.
Please suggest me how to this.
Thanks in advance.
|
|
|
|
|
There's two way to do this without using a loop. The best way is to have your database server get you the data in the fashion you want using a SELECT query. An alternative is to use LIST to do it. In either case, hopefully, you have key relationships between these two tables, right?
|
|
|
|
|
Hi thanks for your response.
But as i told in my post, there is no relation ship between them. Just they are totally 2 different tables, Only the no.of records were same.
I can't get the data from database as you told, bcz no key relation ship between them.
Any alternative.
|
|
|
|
|
Then you have no choice but to loop through them and build it yourself. You'll have to take care to make sure the records are matched up the way you want them. If all you did was retrieve the data with something like: SELECT * FROM table with no sorting information, you can get the records without an guarantee of the order of them, from both tables. It's up to you to match the records up yourself.
|
|
|
|
|
Hi everybody,
I need a multi-thread blocking queue to implement producer/consumer pattern in C#. I have found many BlockingQueue implementations around the internet. But I don't know which one is better. Which one do you recommend me?
Regards
|
|
|
|
|
It depends. How are you going to use it? Will you put ValueTypes in it? Would it be OK if the buffer was fixed sized? If the answer is yes to both, I would pick one that uses a circular array and two Semaphores.
Which implementations are we allowed to choose from?
|
|
|
|
|
Well, what I'm trying to do is a protocol stack implementation with layer abstraction.
So, the communication between layers should be a product/manager scenario. I don't know if I'm right.
So, I'm going to exchange my own objects in these queues.
I suppose, the buffer shouldn't be fixed sized. I know it can be less eficient, but the size should grow when it's needed.
The BlockingQueue implementation i have right now (I can't test it yet) is this:
public class BlockingQueue<T> : IEnumerable<T>
{
private int _count = 0;
private Queue<T> _queue = new Queue<T>();
public T Dequeue()
{
lock (_queue)
{
while (_count <= 0)
Monitor.Wait(_queue);
_count--;
return _queue.Dequeue();
}
}
public void Enqueue(T data)
{
if (data == null)
throw new ArgumentNullException("data");
lock (_queue)
{
_queue.Enqueue(data);
_count++;
Monitor.Pulse(_queue);
}
}
IEnumerator<T> IEnumerable<T>.GetEnumerator()
{
while (true) yield return Dequeue();
}
IEnumerator IEnumerable.GetEnumerator()
{
return ((IEnumerable<T>)this).GetEnumerator();
}
}
Regards
|
|
|
|
|
Should it really be allowed to grow unbounded?
What's worse, your use of Pulse/Wait + lock looks completely wrong to me - since it's locked those pulse/wait are never going to be useful (well it's locked) so Dequeue will wait forever, it can never be Pulsed out of its Wait since Enqueue can not acquire its lock.
Silly moment, scratch that.
So, how about this?
Like so: (untested!)
public class BlockingQueue<T> : IEnumerable<T>
{
private Queue<T> _queue = new Queue<T>();
private Semaphore _semaphore = new Semaphore(0, a lot);
public T Dequeue()
{
_semaphore.WaitOne();
lock (_queue)
return _queue.Dequeue();
}
public void Enqueue(T data)
{
lock (_queue)
_queue.Enqueue(data);
_semaphore.Release();
}
IEnumerator<T> IEnumerable<T>.GetEnumerator()
{
while (true) yield return Dequeue();
}
IEnumerator IEnumerable.GetEnumerator()
{
return ((IEnumerable<T>)this).GetEnumerator();
}
}
That, of course, still requires locking, since operations on a Queue<T> are not thread safe. So it's dead slow. All the time. Not only when there is too much stuff to put into the buffer (which is when it doesn't matter much if the producer gets slowed down a bit since the consumer is the bottleneck anyway)
modified on Monday, January 11, 2010 11:48 AM
|
|
|
|
|
There is an example in this article: Thread synchronization: Wait and Pulse demystified[^]
Your implementation looks correct, but I guess you want to limit the size of the queue at some point, not let it grow to infinity. The implementation in that article also allows you to terminate the queue cleanly.
Or you might find something in the recent release of MS Reactive Extensions on DevLabs[^]. It contains an ( unsupported ) back port of the new .NET 4.0 Task Parallel Library for .NET 3.5. I haven't explored it yet, but I would be surprised if it didn't contain the concurrent collection, including BlockingCollection .
Nick
----------------------------------
Be excellent to each other
|
|
|
|
|
Hi.
I am making just a simple socket program. Server program is always working. When I open client program and click the button, sending/receiving data normally. Everything's ok. But when I close client and opening again, and then clicking button, client program getting lock. Not getting error. When I debug, its waiting on "readline" line. What is the problem? Why its not working when I reopen client program?
Client
private void Form1_Load(object sender, EventArgs e)
{
try
{
tcp_client = new TcpClient("192.168.1.222", 4444);
}
catch
{
label2.Text = "not connected";
return;
}
ag_akimi = tcp_client.GetStream();
akim_okuyucu = new StreamReader(ag_akimi);
akim_yazici = new StreamWriter(ag_akimi);
}
private void button1_Click(object sender, EventArgs e)
{
try
{
akim_yazici.WriteLine("sample ");
akim_yazici.Flush();
textBox1.Text += akim_okuyucu.ReadLine();
}
catch
{
MessageBox.Show("error!");
}
}
private void form_kapatiliyor(object sender, FormClosingEventArgs e)
{
try
{
akim_okuyucu.Close();
akim_yazici.Close();
ag_akimi.Close();
istemcisoketi.Close();
}
catch
{
MessageBox.Show("Not properly closed");
}
}
}
***********************************************
server
public void Form1_Load(object sender, EventArgs e)
{
CheckForIllegalCrossThreadCalls = false;
thread_dinleyici = new Thread(new ThreadStart(dinle));
thread_dinleyici.Start();
}
public void dinle()
{
tcp_listener = new TcpListener(IPAddress.Any, 4444);
tcp_listener.Start();
istemcisoketi = tcp_listener.AcceptSocket();
ag_akimi = new NetworkStream(istemcisoketi);
if (istemcisoketi.Connected)
{
while (true)
{
akim_yazici = new StreamWriter(ag_akimi);
akim_okuyucu = new StreamReader(ag_akimi);
try
{
richTextBox1.Text += akim_okuyucu.ReadLine();
akim_yazici.WriteLine("message");
akim_yazici.Flush();
}
catch
{
label1.Text = "closing";
istemcisoketi.Close();
ag_akimi.Close();
akim_yazici.Close();
akim_okuyucu.Close();
istemcisoketi.Close();
return;
}
}
}
else
{
}
}
|
|
|
|
|
When you load your server form, it starts a thread which is listening for the Client socket.
When the client connects, all is fine.
When the client completes, you close the socket, and exit the "dinle" method via the catch block.
This terminates the thread, so there is nothing listening for the client any more. It then hangs, waiting for the server.
What you need to do is to restart a new thread when the old one closes. Make sure you have some way of terminating threads cleanly, or you will have problems shutting the server down.
All those who believe in psycho kinesis, raise my hand.
|
|
|
|
|
Thanks for your reply.
But how can I restart a new thread when the old one closes? If I didnt write "return" and close thread, I am getting another problems.
|
|
|
|
|
Probably the easier way to do it with your existing code is to move the listening outside the "dinle" method:
public void dinle()
{
while (!AbortAll)
{
DoThread();
}
}
private void DoThread()
{
tcp_listener = new TcpListener(IPAddress.Any, 4444);
tcp_listener.Start();
...
}
catch
{
...
return;
}
}
}
}
All those who believe in psycho kinesis, raise my hand.
|
|
|
|
|
What is "AbortAll"? Is this a variable or?
|
|
|
|
|
Remember I said you would need someway to stop them? It's just a variable - when you start killing things, you can stop the task with it, once you have closed the connection in your main routine. (I have only ever been a fan of "while(true)" loops in real-time software!)
All those who believe in psycho kinesis, raise my hand.
|
|
|
|
|
I am trying to read text from an external application using GetWindowText. It works just fine for all of the other languages in the software I am trying to read from. (German, English, French) However, it fails when it tries to read in Cyrillic (Russian), Arabic, Japanese. All it gets is a bunch of question marks. Here is the code that I am using.
[DllImport("User32.dll", CharSet = CharSet.Unicode)]
public static extern Int32 GetWindowText(int hWnd, StringBuilder s, int nMaxCount);
Win32.GetWindowText(hWnd, formDetails, 512);
When I display the text using a textbox is is merely a bunch of "?????? ????? ?? ???????".
I know it has nothing to do with the textboxes inability to display those languages because if I directly drop a string of Cyrillic into a variable in C# and display it in the box, it display just fine. What am I doing wrong?
-Elmernite
|
|
|
|
|
Message Closed
modified 23-Nov-14 7:12am.
|
|
|
|
|
I've read it, but that doesn't really help, unless I missed it somewhere.
See as a general rule, my program doesn't really display the other languages (what the article you post was mostly about), I just need to read in the languages of the other software so I know what language that software is currently in.
I'm guessing the GetWindowText or StringBuilder has problems reading in the aforementioned languages. That is what I need help with.
-Elmernite
|
|
|
|
|
I want to create a DataGridView with custom headings. Basically, I want to place a Panel with a number of controls in each heading cell. To do this I have created a new class which inherits DataColumn:
public class GenericDataColumn : DataColumn
{
private int columnIndex;
private string columnName;
private Panel panel;
private DataGridView table;
private Size initialPanelSize;
private Point[] initialControlLocations;
public GenericDataColumn(int columnIndex,
string columnName,
Panel panel,
DataGridView table)
{
this.columnIndex = columnIndex;
this.ColumnName = columnName;
this.table = table;
this.panel = panel;
this.initialPanelSize = panel.Size;
this.initialControlLocations = new Point[panel.Controls.Count];
for (int i = 0; i < panel.Controls.Count; i++)
{
initialControlLocations[i] = panel.Controls[i].Location;
}
}
}
Whenever the table is scrolled or resized or the column is resized I need to resize the Panel and possibly move around the controls inside the Panel. I wrote the following method to do that:
private void cutPanel(int cutFromLeft, int cutFromRight)
{
int newPanelWidth = initialPanelSize.Width;
if (0 < cutFromLeft)
{
newPanelWidth -= cutFromLeft;
}
if (0 < cutFromRight)
{
newPanelWidth -= cutFromRight;
}
panel.Width = newPanelWidth;
if (0 <= cutFromLeft)
{
for (int i = 0; i < panel.Controls.Count; i++)
{
panel.Controls[i].Location = new Point(
initialControlLocations[i].X - cutFromLeft,
initialControlLocations[i].Y);
}
}
}
In the Paint event I can easily determine what the new position and dimension of the Panel should be:
DataGridView.GetCellDisplayRectangle(columnIndex, -1, true);
However, this information alone is not enough to determine the cutFromLeft and cutFromRight parameters in the cutPanel method. What's the best way to determine those parameters? Am I forced to micro-manage all the "geography-related" events (DataGridView scroll, DataGridView resize, and column resize) or is there an easier way to do it?
|
|
|
|
|
Just a wild guess from my side:
How about setting AutoSize property of the Panel to true or to set its Dock property to fill.
50-50-90 rule: Anytime I have a 50-50 chance of getting something right, there's a 90% probability I'll get it wrong...!!
|
|
|
|
|
No, unfortunately that won't work. Whenever a "geographical" event occurs, we are responisble for moving and resizing the Panel according to the new header cell location and size. No auto-property is smart enough to do this.
|
|
|
|
|
I was hoping that Panel would be the Column's control and then this should work when you re-size the column. I guess that is not the case.
Now, IMHO, the only way is to track the resize and do the same for the Panel.
50-50-90 rule: Anytime I have a 50-50 chance of getting something right, there's a 90% probability I'll get it wrong...!!
|
|
|
|
|
Oh, I see, you're suggesting I should add the Panel to the GenericDataColumn instead of the DataGridView. I will try that and see what happens.
|
|
|
|
|