|
I am attempting to write a command queue. It is important that each command is executed in order (FIFO). This command queue will be running functions that will have to interact with controls using Control.Invoke . The problem I am having has to do with threading and is harder to describe then to show. Code Follows:
public struct CommandContainer
{
public System.Delegate method;
public object[] parameters;
}
CommandQueue.cs
-------------------------
using System;
using System.Threading;
using System.Windows.Forms;
namespace CommandQueue
{
public delegate void CommandFunction();
public class CommandQueue:System.Collections.Queue
{
private ManualResetEvent m_ManualResetEvent;
public CommandQueue()
{
}
public override void Clear()
{
lock(this.SyncRoot)
{
base.Clear ();
}
}
public override object Dequeue()
{
lock(this.SyncRoot)
{
return base.Dequeue ();
}
}
public override object Peek()
{
lock(this.SyncRoot)
{
return base.Peek ();
}
}
public override void Enqueue(object obj)
{
lock(this.SyncRoot)
{
if(obj is CommandContainer)
{
base.Enqueue (obj);
}
else
{
}
}
}
public void Enqueue(CommandFunction target)
{
lock(this.SyncRoot)
{
CommandContainer t_CommandContainer;
t_CommandContainer.method = target;
t_CommandContainer.parameters = null;
base.Enqueue (t_CommandContainer);
}
}
public void Enqueue(System.Delegate method, object[] parameters)
{
lock(this.SyncRoot)
{
CommandContainer t_CommandContainer;
t_CommandContainer.method = method;
t_CommandContainer.parameters = parameters;
base.Enqueue (t_CommandContainer);
}
}
public void Flush()
{
Thread t_FlushThread = new Thread(new ThreadStart(FlushThreadStart));
t_FlushThread.Name = "Flush Thread";
t_FlushThread.Start();
t_FlushThread.Join();
}
private void FlushThreadStart()
{
lock(this.SyncRoot)
{
for(int i = 0; i < this.Count; i++)
{
Thread t_RunThread = new Thread(new ThreadStart(RunCommand));
t_RunThread.Name = i.ToString() + " : " + ((CommandContainer)base.Peek()).method.Method.ToString();
t_RunThread.Start();
t_RunThread.Join(500);
}
}
}
private void RunCommand()
{
object t_Command = base.Dequeue();
if(t_Command is CommandContainer)
{
CommandContainer t_CommandContainer = (CommandContainer)t_Command;
t_CommandContainer.method.DynamicInvoke(t_CommandContainer.parameters);
}
}
}
}
Form1.cs
----------------
using System;
using System.Drawing;
using System.Collections;
using System.ComponentModel;
using System.Windows.Forms;
using System.Data;
namespace CommandQueue
{
public class Form1 : System.Windows.Forms.Form
{
CommandQueue CQ = new CommandQueue();
private System.Windows.Forms.Button button1;
private System.ComponentModel.Container components = null;
public Form1()
{
InitializeComponent();
}
protected override void Dispose( bool disposing )
{
if( disposing )
{
if (components != null)
{
components.Dispose();
}
}
base.Dispose( disposing );
}
#region Windows Form Designer generated code
private void InitializeComponent()
{
this.button1 = new System.Windows.Forms.Button();
this.SuspendLayout();
this.button1.Location = new System.Drawing.Point(8, 8);
this.button1.Name = "button1";
this.button1.Size = new System.Drawing.Size(72, 40);
this.button1.TabIndex = 0;
this.button1.Text = "button1";
this.button1.Click += new System.EventHandler(this.button1_Click);
this.AutoScaleBaseSize = new System.Drawing.Size(5, 13);
this.ClientSize = new System.Drawing.Size(292, 273);
this.Controls.Add(this.button1);
this.Name = "Form1";
this.Text = "Form1";
this.ResumeLayout(false);
}
#endregion
[MTAThread]
static void Main()
{
Application.Run(new Form1());
}
private void button1_Click(object sender, System.EventArgs e)
{
for(int i =0; i< 2; i++)
{
CQ.Enqueue(new CommandFunction(Fctn0));
CQ.Enqueue(new CommandFunction(Fctn1));
CQ.Enqueue(new CommandFunction(Fctn2));
CQ.Enqueue(new CommandFunction(Fctn3));
}
CQ.Flush();
}
private void Fctn0()
{
Console.WriteLine("0");
}
private void Fctn1()
{
Console.WriteLine("1A");
this.button1.Invoke(new CommandFunction(foo));
Console.WriteLine("1B");
}
private void Fctn2()
{
Console.WriteLine("2");
}
private void Fctn3()
{
Console.WriteLine("3");
}
private void foo()
{
Console.WriteLine("Foo invoked from Fctn1");
}
}
}
OUTPUT:
The thread '0 : Void Fctn0()' (0x5f0) has exited with code 0 (0x0).
0
1A
The thread '2 : Void Fctn2()' (0x878) has exited with code 0 (0x0).
2
3
The thread '3 : Void Fctn3()' (0x894) has exited with code 0 (0x0).
The thread 'Flush Thread' (0x8d4) has exited with code 0 (0x0).
The thread '1 : Void Fctn1()' (0x54c) has exited with code 0 (0x0).
Foo invoked from Fctn1
1B
The problem is in function Fctn1() of Form1. It should output a “1A” followed by a “1B” in the console. Instead the Invoke call in Fctn1() appears to be voiding the Join(500) Call in FlushThreadStart() of CommandQueue.cs. I don’t care if the invoked code executes immediately, but why is the rest of the function waiting and how is it getting past the Join? Using a ManualResetEvent causes a deadlock. Any help would be appreciated.
|
|
|
|
|
It simply means that Invoke took more than 500 ms and so the FlushThreadStart continued to execute other functions while Fctn1 was waiting for the Invoke to complete.
I don't understand why you are running each command in a separate thread. You said that you want to execute them in the same order, so instead of starting a thread and then waiting for it to complete, why not just execute it synchronously?
Regards
Senthil
_____________________________
My Blog | My Articles | WinMacro
|
|
|
|
|
I guess I thought Join(500) would kill the thread after 500ms. I must have misread that somewhere.
|
|
|
|
|
criteria exams=50% quizzes=10% daily= 10% assignments= 30%
this is the program I would like to revise
include<stdio.h>
void main (void)
{
double gpa,exam,quiz,assign,prof;
printf("\n enter the exam grade:");
scanf("%lf", &exam);
printf("\n enter the quiz grade:");
scanf("%lf",& quiz);
printf("\n enter the assign grade:");
scanf("%lf",& assign);
printf("\n enter the prof grade:");
scanf("%lf",& prof);
gpa=((exam*.6)+(quiz*.1)+(assign*.2)+(prof*.1));
printf("\n the gpa is %.2lf", gpa);
}
|
|
|
|
|
This is the C# Forum, not C++...
You might want to actually ask a question with whatever your having a problem with. DO NOT just say you want to revise this program. Since this is a homework project, you actually have to write the code. We'll help you with any problems your having, but will NOT write the code for you.
RageInTheMachine9532
"...a pungent, ghastly, stinky piece of cheese!" -- The Roaming Gnome
|
|
|
|
|
What Dave said. Your code is also not valid C++, it returns void instead of int. That your compiler sucks is no excuse
Christian Graus - Microsoft MVP - C++
|
|
|
|
|
Christian Graus wrote:
That your compiler sucks is no excuse
#include <stdio.h>
void main()
{
printf("Hello World\n");
}
Is a perfect valid C/C++ program.
Compiled on VS.NET 2003 and 2005 Express , no warnings, no errors, runs correctly.
Compiled on GCC 3.4.3, gives return type warning, runs correctly.
Being ignorant is no excuse.
xacc-ide 0.0.15 now with C#, MSIL, C, XML, ASP.NET, Nemerle, MyXaml and HLSL coloring - Screenshots
|
|
|
|
|
|
leppie wrote:
Being ignorant is no excuse.
Then you're screwed
The C++ standard says main returns int.
|
|
|
|
|
Hello,
Here's my problem: I have to replace all instances of a certain string in binary values. I was using ASCIIEncoding to get the bytes to a string, performing the replace, then using ASCIIEncoding to get the string back to byte[]. This was working for most of my tests but then I ran into binary values that were getting corrupted during the conversion. I wrote the following test code:
// myRegKey is a RegistryKey object
// ValueName is a string (the name of the value I want to retrieve from the registry)
object valData = myRegKey.GetValue(ValueName);
ASCIIEncoding ae = new ASCIIEncoding();
byte[] buff = (byte[])valData;
string tmp = ae.GetString(bite);
byte[] buff2 = ae.GetBytes(tmp);
So I would expect that buff and buff2 would be identical, but they are not!
I need a way to get a byte[] to a string and then back to a byte[] without compromising my data. Any ideas?
Perhaps if someone had a method that converts a binary value to a string of hex digits? For example, "Hello World!" would become "48656C6F20576F726C6421"
Thanks,
-Ian
|
|
|
|
|
i guess with something like
stringbuilder sb;
string s
char[] ca
ca = s.ToCharArray(0,s.Length);
a for loop
sb.Append(((byte)ca[i]).ToString("X"));
its a lame code i know
|
|
|
|
|
|
I want to transfer a class instance on internet and encrypt this instance. But the encryption classes requieres byte[]. how can I get the byte[] representation of an instance?
|
|
|
|
|
|
I know PHP and Java, and I'm just starting to learn C#, so I don't know many of the C# methods.
I'm trying to write a method that will open a bmp image and save it on the hard drive. I want to compile the image with the program, so I added it as an item in the Solution Explorer, but now I dont know how to access it.
What method do I use to access it?
Thanks
|
|
|
|
|
wetdog500 wrote:
so I added it as an item in the Solution Explorer
Umm.. what exactly did u added and how?
To open a bitmap and save it somewhere else on ur machine you could say:
System.Drawing.Bitmap myB = new System.Drawing.Bitmap(@"C:\myBitmap.bmp");<br />
<br />
myB.Save("......");
Regards,
Polis
Can you practice what you teach?
|
|
|
|
|
In the Solutions Explorer I right clicked on my project's name then went to 'Add', 'Add Existing Item...'.
Next I selected a .bmp image and hit enter.
Does that help?
|
|
|
|
|
wetdog500 wrote:
In the Solutions Explorer I right clicked on my project's name then went to 'Add', 'Add Existing Item...'.
Well, not really. What you did, is just adding a specific bitmap image as a resource into your solution. If all u need is opening a bitmap during runtime and save it somewhere else, you just have to follow the small code sample I provided you with before.. or something similar.
Hope this helps
Regards,
Polis
Can you practice what you teach?
|
|
|
|
|
Thanks, but what path do I use to access the image?
|
|
|
|
|
Well, that's up to you.
I think that you would want your users to be able to specify the path to a bitmapt for themselves by browsing for a specific file or typing down the filename path for themselves. It wouldn't really made much sense to just specify a fixed filename path in your code right?
A simple example:
You could drop two textboxes and a button on your form. The users would then type a path to a bitmap in the first textbox, the new path to which the bitmap will be copied in the second textbox (if it does exists under that path), and finally press the button to actually copy the bitmap.
On the button click event you could have something like this:
Bitmap myBitmap = new Bitmap(this.textbox1.text);<br />
<br />
myBitmap.Save(this.textbox2.text);
A small tip:
Btw, you would have to provide some checkups. E.g. make sure that the path names the user provided are valid before attempting to load a bitmap. Or, make sure that the user HAS provided paths for both textboxes.
Regards,
Polis
Can you practice what you teach?
|
|
|
|
|
No, I'm sorry I didn't explain myself well enough.
I want to have the user copy a resource in my program, not on the hard disk, to a loction on their hard disk.
How do I access that resource?
|
|
|
|
|
wetdog500 wrote:
How do I access that resource?
To programmatically access one of your resources you could say something like:
Assembly myAssembly = GetExecutingAssembly();
Stream resourceStream = myAssembly.GetManifestResourceStream("myBitmap.bmp");
Bitmap image = new Bitmap(resourceStream);
wetdog500 wrote:
I want to have the user copy a resource in my program
I am not sure whether you can do that. Resources are part of your assembly and are included in it every time you compile your program
Regards,
Polis
Can you practice what you teach?
|
|
|
|
|
|
It's alright. Glad I could help
Regards,
Polis
Can you practice what you teach?
|
|
|
|
|