|
Creating the PictureBoxes and adding them to the Panel must be done on the main UI thread. So there is a limit to how much work you can offload to a worker thread.
If calculating the size and location is taking a long time, maybe you should look at optimising that code. Modern computers are extremely fast at calculations, so I would be surprised if this was the bottleneck.
You could try allowing the UI to process any messages in it's message queue between calls to AddImage by having a queue of images to add and Posting a custom message to the end of the message queue after each addition. Then the custom message handler would be responsible for actually doing the work one image at a time.
Nick
----------------------------------
Be excellent to each other
|
|
|
|
|
Aha, I think you've touched exactly on my problem. I've been adding the PictureBoxes from the worker thread. At first I had exception complaining about it being done from a different thread than the one the Panel was created on so I added code to make it thread safe as per this example on MSDN[^] (looking at the SetText function). Is that incorrect then?
I don't think its the calculating of size and position that really takes up time but rather the instantiating of new PictureBoxes and then the UI work of actually adding them to the Panel . I don't mind it taking a while to add the pictures to the panel, I just don't want the main form to have to wait for it all to finish before it can start accepting button clicks again.
I'll look into this suggestion of using a queue. I think that might just be the first step towards a real sollution, thanks. That said, any further advice would be appreciated.
|
|
|
|
|
The article shows you how to marshal back to the UI thread. Doing it this way is probably just adding overhead to the process.
Do you know how to PostMessage ( http://www.pinvoke.net/default.aspx/user32/PostMessage.html[^] ) a user message and catch it in your override of Control.WndProc ? That's what I would try.
You can also use BeginInvoke , as that posts a message for you, if you don't want to use PInvoke. You have to call EndInvoke , though. I think this is a bit harder, but it is an all managed code solution.
Nick
----------------------------------
Be excellent to each other
|
|
|
|
|
OK thanks, I'll have a look into those. A part of me feels that this couldn't be so unusual a scenario that it should be neccesary to turn to unmanaged code or am I wrong?
I think I'll investigate the BeginInvoke and EndInvoke option but I'm a little confused, what exactly is the difference between BeginInvoke and Invoke which I've been using?
|
|
|
|
|
Dewald wrote: what exactly is the difference between BeginInvoke and Invoke which I've been using?
BeginInvoke follows assynchronous fashion calls. So it won't block and will return to the caller immediatly. Invoke blocks the calling thread until the message is handled. Here[^] is an excellent article which talks on this.
|
|
|
|
|
Cool, that is indeed an excellent article. It puts things into perspective but I have to say that I'm getting very frustrated here. I was convinced that I was threading correctly, only to change my mind later that I'm definitely doing it wrong (leading to me posting the question). After reading this article I'm convinced again that I have been doing it right (although I've used Invoke as opposed to BeginInvoke ). The problem is, as convinced as I am that I'm doing it right, my app is still not working so obviously I AM doing it wrong.
I would so appreciate if someone could take the time to look at what I'm doing and point out where I'm getting it wrong. Basically what I'm doing is the following:
I have a member in my main form class
private BackgroundWorker MyWorker;
in the constructor of the main form, after InitializeComponent() I set the worker up as follows:
MyWorker = new BackgroundWorker();
MyWorker.WorkerSupportsCancellation = true;
MyWorker.DoWork += new DoWorkEventHandler(MyWorker_DoWork);
The worker function is simply defined as following:
void MyWorker_DoWork(object sender, DoWorkEventArgs e)
{
SetImages((string)e.Argument, sender as BackgroundWorker, e);
}
The SetImages function extracts the images to be added to my custom control from a DB and calls, for every image, the custom control's AddPicture method which is thread safe by using InvokeRequired and BeginInvoke as described in the article.
Also inside SetImages , the first step at every iteration, before adding an image, is to execute the following code:
if (worker.CancellationPending)
{
e.Cancel = true;
return;
}
To add a bunch of images to the control I can now simply call
MyWorker.RunWorkerAsync(someStringValue); the input string determining which collection of images are to be added to the control.
This works perfectly but what doesn't work is when I'm trying to interrupt the worker and call it again with a new input string. The code I'm using for that is as follows:
while (MyWorker.IsBusy)
MyWorker.CancelAsync();
MyWorker.RunWorkerAsync(someStringValue);
The problem is that MyWorker.IsBusy remains true and the little while-loop never exits. I would have thought that checking worker.CancellationPending and setting e.Cancel = true in SetImages should be sufficient to interrupt execution of the thread but it seems not to be.
What am I doing wrong? This is starting to really frustrate me!
|
|
|
|
|
Put Debug.WriteLine in the areas you suspect. It gives you how the code is executing. CancelAsync() just sets the CancellationPending flag to true and won't block the caller.
This might be the reason your loop is going infinite. You can use wait handles, and wait until the worker cancels. In the RunWorkerCompleted event handler, check Cancelled property. If it is cancelled, set the waithandle which will run the next line ie, RunWorkerAsync() . Something like
MyWorker.CancelAsync();
waitHandle.WaitOne();
MyWorker.RunWorkerAsync(someStringValue);
if(e.Cancelled)
waitHandle.Set(); You can use AutoResetEvent as waithandle.
I might be wrong as I haven't tested this. It's a guess. Try your luck.
Dewald wrote: the custom control's AddPicture method which is thread safe by using InvokeRequired and BeginInvoke as described in the article.
AFAIK, controls are usually not made as thread safe. Since you are using BackgroundWorker , you can update controls safely from ProgressChanged event handler.
|
|
|
|
|
Sounds like you're making progress
You should use Invoke not BeginInvoke in AddPicture if you're using a thread. Otherwise, the thread will not block and will loop round adding all the images without waiting for each image to be added.
For the interrupt method, just call CancelAsync once, and then handle the RunWorkerCompleted event.
Nick
----------------------------------
Be excellent to each other
|
|
|
|
|
COOL BANANAS!!!! You're my new best friend. Thanks for the help, both of you, I've learned a lot.
|
|
|
|
|
Is there a BinarySearch for IList<T> - or a similar generic BinarySearch?
Couldn't find any besides the (non-generic) Array.BinarySearch
|
|
|
|
|
peterchen wrote: Couldn't find any besides the (non-generic) Array.BinarySearch
There is a generic version of Array.BinarySearch . You can use that to search in IList(T) . Assume you have sorted strings in IList(T) .
int index = Array.BinarySearch<string>(list.ToArray<string>(), "SearchString"); list.ToArray<string>() is an extension method. If you are on .NET 2.0, you won't see this.
Hope it helps
|
|
|
|
|
public static class IListExtensions
{
public static int BinarySearch<T>(this IList<T> list, T item, Comparison<T> comp)
{
if (list == null) throw new ArgumentNullException("list");
if (comp == null) throw new ArgumentNullException("comp");
if (list.Count == 0)
return -1;
return BinarySearch(list, item, comp, 0, list.Count - 1);
}
private static int BinarySearch<T>(IList<T> list, T item,
Comparison<T> comprasion, int start, int end)
{
while (true) {
int i = (end + start) / 2;
int cmp = comprasion(item, list[i]);
if (cmp == 0)
return i;
else if (cmp > 0) {
if (i == end)
return -1;
start = i + 1;
}
else {
if (i == start)
return -1;
end = i - 1;
}
}
}
} Hope this helps .
Greetings - Gajatko
Portable.NET is part of DotGNU, a project to build a complete Free Software replacement for .NET - a system that truly belongs to the developers.
|
|
|
|
|
I take report to show data from table/gridview;
using
private void show_Click(object sender, EventArgs e)
{
SqlDataAdapter da = new SqlDataAdapter("Select * From User_Detail where CDate='" + dateTimePicker1.Text + "' And Username='" + comboBox2.Text + "'", con);
MessageBox.Show(dateTimePicker1.Text.ToString());
DataTable dt1 = new DataTable ();
da.Fill(dt1);
dataGridView1.DataSource = dt1;
if(dt1.Rows.Count!=0)
{
employeereport Emp = new employeereport();
Emp.SetDataSource(dt1);
crystalReportViewer1.ReportSource = Emp;
}
}
that cannot show data related to given date???
all data can be shown but in gridview perfect data can be shown??
Plz tell me where is problem????
|
|
|
|
|
hello every one,
I want to build my database files -data & log files- related to the path of the .exe file of my program that is a setup project,
how to do this?
regards
|
|
|
|
|
|
hi
i must working on StgOpenStorageEx(ole32) bez. i used windows xp
and in www.pinvoke.net
give this defined
DllImport("ole32.dll")]
static extern int StgOpenStorageEx([MarshalAs(UnmanagedType.LPWStr)] string
pwcsName, uint grfMode, uint stgfmt, uint grfAttrs, ref STGOPTIONS
pStgOptions, IntPtr reserved2, [In] ref Guid riid,
[MarshalAs(UnmanagedType.IUnknown)] out object ppObjectOpen);
my problem is in this parameter (ref STGOPTIONS pStgOptions) what i must value give it?????
im searching and am trying
if u can please help me
|
|
|
|
|
The page on pinvoke that shows the definition has an example too. Why don't you have a look at it?
|
|
|
|
|
hi
thanks for answering
but this function any example or detailes not found on it>>
can u give the page or site
i enter msdn but it not enagh
THANX
|
|
|
|
|
|
No real point in replying to the OP. They ask the same garbage over and over.
"The clue train passed his station without stopping." - John Simmons / outlaw programmer
"Real programmers just throw a bunch of 1s and 0s at the computer to see what sticks" - Pete O'Hanlon
"Not only do you continue to babble nonsense, you can't even correctly remember the nonsense you babbled just minutes ago." - Rob Graham
|
|
|
|
|
How many weeks (months?) have you been trying to call 1 method for now?
|
|
|
|
|
Whenever I try to encrypt or hide my strings my program immediately crashes when I double click the .exe. Does anyone have a clue of why this may be happening. I'm using 9Rays.net Obfuscation.
Thanks,
Buckley.
|
|
|
|
|
It might be another setting in the 9rays software causing the crash. Have you asked 9Rays about it?
"Why don't you tie a kerosene-soaked rag around your ankles so the ants won't climb up and eat your candy ass..." - Dale Earnhardt, 1997 ----- "...the staggering layers of obscenity in your statement make it a work of art on so many levels." - Jason Jystad, 10/26/2001
|
|
|
|
|
Buckleyindahouse wrote: why this may be happening. I'm using 9Rays.net Obfuscation.
Try contacting 9Rays and see what they say.
"The clue train passed his station without stopping." - John Simmons / outlaw programmer
"Real programmers just throw a bunch of 1s and 0s at the computer to see what sticks" - Pete O'Hanlon
"Not only do you continue to babble nonsense, you can't even correctly remember the nonsense you babbled just minutes ago." - Rob Graham
|
|
|
|
|
I draw the string("ABCDEFGH")or Square in panel using c#.I want to rotate the shape
in any angles.Please help me how to find the Center point and rotate the shape.
Note: I used DrawLine() method to draw shapes
|
|
|
|