|
Hi Kurt,
The System.ComponentModel namespace contains the AsyncOperation class which enables a thread to raise events on the GUI thread. I won't try and modify your code as my knowledge of network programming is minimal but instead I present a simple example showing the basics.
using System;
using System.ComponentModel;
using System.Threading;
namespace WorkerThreadEvent {
class EventThread {
private AsyncOperation operation;
public event EventHandler<ProgressChangedEventArgs> ProgressChanged;
private void OnProgress(Object progress) {
EventHandler<ProgressChangedEventArgs> handler = ProgressChanged;
if (handler != null) {
ProgressChangedEventArgs args = new ProgressChangedEventArgs((int)progress, null);
handler(this, args);
}
}
public void Run() {
operation = AsyncOperationManager.CreateOperation(null);
ThreadPool.QueueUserWorkItem(new WaitCallback(ThreadProc), null);
}
private void ThreadProc(Object state) {
try {
for (int i = 1; i <= 100; i++) {
Thread.Sleep(100);
operation.Post(new SendOrPostCallback(OnProgress), i);
}
} finally {
operation.OperationCompleted();
}
}
}
}
The only real changes to standard event coding are
1) Creation of an AsyncOperation
2) Use of the operation's Post method to marshal the event to the thread that called AsyncOperationManager.CreateOperation(null)
3) Ending the operation correctly when it no longer needed
You can incorporate this class in a simple winforms app and you'll find that the ProgressChanged event is raised on the GUI thread and there will be no need to use invoke to update the display.
I use the AsyncOperation quite often now as it really simplifies UI coding in a multithreaded programme and I'm sure that many more people would too if only the documentation on MSDN was better. An example like the one above might help!
Alan.
By the way I think that the technique I have shown is similar to the way that the BackgroundWorker class marshals events to the GUI thread.
And it would be remiss of me not to reference this excellent article by Leslie Sanford.
http://www.codeproject.com/KB/cpp/SyncContextTutorial.aspx[^]
modified on Friday, October 24, 2008 2:29 PM
|
|
|
|
|
I searched for ISynchronizeInvoke and found a complete solution for thread safe events instead.
This solution is from http://www.gmbsg.com/works/index.php?title=Events_threadsicher_aufrufen_in_.NET[^]
public static class ThreadSafe
{
public static void Invoke(Delegate method, object[] args)
{
if (method != null)
{
foreach (Delegate handler in method.GetInvocationList())
{
if (handler.Target is Control)
{
Control target = handler.Target as Control;
if (target.IsHandleCreated)
{
target.BeginInvoke(handler, args);
}
}
else if (handler.Target is ISynchronizeInvoke)
{
ISynchronizeInvoke target = handler.Target as ISynchronizeInvoke;
target.BeginInvoke(handler, args);
}
else
{
handler.DynamicInvoke(args);
}
}
}
}
}
public void OnDataReceived(object sender, DataReveivedEventArgs e)
{
if (DataReceived != null) { ThreadSafe.Invoke(this.DataReceived, new object[] { this, e });
}
It works great! No invoke outside my class is needed anymore!
|
|
|
|
|
Hi
We've developed open-source ASP.NET shopping cart. nopCommerce is a open source e-commerce solution that is ASP.NET 3.5 (C#) based with a MS SQL 2005 (or higher) backend database. nopCommerce is available for free. If somebody will be interested in reviewing it please visit http://www.nopCommerce.com
Thank you!
nopCommerce is the open-source eCommerce solution. nopCommerce is available for free.
http://www.nopCommerce.com
|
|
|
|
|
Hi all,
Does someone know if it is possible to access a variable and change the name of the variable based on a condition. (This does not make much sense but let me explain it using the example below.
I have two foreach loops, both doing the exact same thing. But it is accessing different variables. I would prefer it if i were to have one foreach loop and access the different variable based on the string that was passed to the function.
Thus having something like (string.Concat(context,"ReadOnlyProperties"))
private void CustomizeEditor(string context)
{
DetailView detailViewCore = (DetailView)View;
Object obj = detailViewCore.CurrentObject;
if (context == "live")
{
foreach (string liveTargetPropertyName in liveReadOnlyProperties.Keys)
{
CriteriaOperator criteria = CriteriaOperator.Parse(liveReadOnlyProperties[liveTargetPropertyName]);
UpdateProperty(detailViewCore, obj, liveTargetPropertyName, criteria);
}
}
else
{
foreach (string saveTargetPropertyName in saveReadOnlyProperties.Keys)
{
CriteriaOperator criteria = CriteriaOperator.Parse(saveReadOnlyProperties[saveTargetPropertyName]);
UpdateProperty(detailViewCore, obj, saveTargetPropertyName, criteria);
}
}
}
Thanks
|
|
|
|
|
You can make a method which contains the loop, and call the method twice passing the variable to loop through..
|
|
|
|
|
private void CustomizeEditor(string context)
{
DetailView detailViewCore = (DetailView)View;
Object obj = detailViewCore.CurrentObject;
string parse, propertyName;
if (context == "live"){
parse = liveReadOnlyProperties[liveTargetPropertyName];
propertyName = liveTargetPropertyName;
keys = liveReadOnlyProperties.Keys;
}
else{
parse = saveReadOnlyProperties[saveTargetPropertyName];
propertyName = saveTargetPropertyName;
keys = saveReadOnlyProperties.Keys;
}
foreach (string propertyName in keys)
{
CriteriaOperator criteria = CriteriaOperator.Parse(parse);
UpdateProperty(detailViewCore, obj, propertyName , criteria);
}
}
|
|
|
|
|
Why not simply pass in the appropriate collection?
|
|
|
|
|
Hello Is there any way to generate automatic customer id in c# windows form. Backend will be SQL Server..
|
|
|
|
|
Make a datatable. Make the customer id field primary key and set its autoincrement property to true.
Ahsan Ullah
Senior Software Engineer
|
|
|
|
|
nt_virus wrote: Backend will be SQL Server..
Use identity column for customer id.
|
|
|
|
|
|
Can u provide a sample code to generate GUID?
|
|
|
|
|
|
|
Try googling or MSDN once in a while, you could have found it in 5 minutes if you tried...
|
|
|
|
|
So I have this idea in my head that will make work easier. Many companies are now implementing web applications. This can be annoying at times. Below I listed some problems and solutions I have with web applications. I am wondering if I should create a stand alone C# application that will run in the task bar to collect any IE windows that have a specific URL or if I should create an IE Addin. The only problem with creating an Addin, is we might be locked down from installing addins, due to virus/spyware. Also, any ideas YOU have, please feel free to share. If I do get a program like this up and running I will share the source code. Thanks, Chris
Problem A:
If you access an external link (ie, from Excel or messaging program) a new web browser will open up.
Solution A:
Use Application/IE Addin to collect IE windows that have the same begining URL (which you could set in a config file)
---
Problem B:
If you are idle for two long your session times out and are asked to log back in before you can resume.
Solution B:
The Application/IE Addin will notice you have gone back to the login page and automatically log you back in. NOTE: We do not want to save the login information; but rather keep it as a varriable in the Application/IE Addin
---
Problem C:
Sometimes if you have lag to the web server you will get a page can not load error and you lose all the date you typed in a web text box.
Solution C:
Everytime you leave a page the applcation/IE Addin will copy the text to your clipboard.
|
|
|
|
|
Can someone please explain me what the above 3 are & how are they to be used in development & how they interact with each other.
Thanks.
|
|
|
|
|
|
I am going to make it simply afterwords read more about it and download sample codes.
A DataGridView is use to display/report data the you have stored somewhere.
DGV is a gentlemen because display everthing regardless of the kind of datatable or dataset, meening that you dont need to create a "suit" that matches 100% your dataset scheme, it loads everthing!!!
For exemple, you can display/report data in crystal reports to, but here, you have to create a dataset scheme to fit your data!!!
A Dataset is a scheme, like: id(int),f_name(string),l_name(string),birth_date(date), it has to match the scheme of what you are loading, a sql databable for exemple, the fields as to be the same kind to fit!
A Datatable is part of a database, nothing here very fancy to know. Sometimes in C# in runtime you dont need to create the database and after the datatable, if you only need 1 datatable.
So, like you see DGV displays data from a datatable that as a dataset scheme, but in others objects like a crystal_report, you need to make a scheme to match the scheme of the datatable you are loading!!! got it???
Good Luck
nelsonpaixao@yahoo.com.br
trying to help & get help
modified on Thursday, October 23, 2008 8:58 PM
|
|
|
|
|
Hi All
Im trying to create a application that can connect connect to he exchange server. In my application i want to add a appoitment,Task List,Calendar. And all that need to connect to Exchange server.
if any one know can you please help me out
Thanks in advance
|
|
|
|
|
Hi, Im trying to define some custom events within one of my classes.
I have set the delegate and the event as follows:
<br />
public delegate void SegmentProgressUpdate();<br />
public event SegmentProgressUpdate ProgressUpdate;
That is just above my constructor.
It compiles, But at runtime when the event gets called I get the "Object reference not set to an instance of an object." Error.
Im sure i am doing something wrong, But i cant see what. I have read a dozen tutorials on custom events online, that all only have what i have above. And i have googled the error related to events but cant find a solution that works.
Does anyone have any idea?
|
|
|
|
|
Abydosgater,
I guessing you don't listen to the event. When you fire the event, check its not null.
if (ProgressUpdate != null)
ProgressUpdate();
Also, its best to try and stick to .net conventions when possible, so your delegate should take 2 params.
public delegate void SegmentProgressUpdate(object sender, EventArgs e);
Sender is the object calling the event, and the event args is the class with the information you'd like to pass, if you don't pass anything, just do a: EventArgs.Empty
Regards,
Gareth.
(FKA gareth111)
|
|
|
|
|
Thanks for the quick reply Gareth.
I have tried this, and it still doesnt work. It doesnt crash with the error but as you will see:
<br />
SegmentOne.ProgressUpdate += new Segment.SegmentProgressUpdate(SegmentOne_ProgressUpdate);
Im listening to the event, Thats in my main application, And i have changed it to this:
<br />
if (ProgressUpdate != null)<br />
{<br />
ProgressUpdate(this, System.EventArgs.Empty);<br />
}<br />
else<br />
System.Windows.Forms.MessageBox.Show("error segment.cs:109");
But now all it does is throw the error message box.
|
|
|
|
|
Abydosgater,
When do you listen to the event?, once you've created SegmentOne? or...?
Regards,
Gareth.
(FKA gareth111)
|
|
|
|
|
Yes once i have created the SegmentOne Object.
<br />
SegmentOne = new Segment(SegmentOneStart, SegmentOneEnd, this._webRequest);<br />
SegmentOne.ProgressUpdate += new Segment.SegmentProgressUpdate(SegmentOne_ProgressUpdate);
Hmm
|
|
|
|