|
And I suspect it would still only verify what's in the controller's cache, not what's actually on the platter.
|
|
|
|
|
Well that would be OS dependent, however, if you sent command directly to the controller I bet you could flush the cache? I bet you can even disable the cache on the HDD with a command. But again, thats why I say just degauss.
Need a C# Consultant? I'm available.
Happiness in intelligent people is the rarest thing I know. -- Ernest Hemingway
|
|
|
|
|
I try reading it but couldn't understand can somebody show me in basic manner how to use and where to use suspendedLayout function in C#.
|
|
|
|
|
Hi,
Some Controls show a collection of items (ListBox, ListView, TreeView, ...). If you add items
one by one then the Control has to update its content every time, since it never knows
whether your Add() is the last one; this may take a lot of time, and cause a lot of flicker.
To avoid these drawbacks, you can typically do two things:
- use AddRange() instead of Add() to group several additions, hence reducing the number
of redraws;
- use SuspendLayout() before, and ResumeLayout() after, the massive add operation.
The final result will be the same, the amount of time and screen disturbance will differ.
|
|
|
|
|
Thanks for answering, but this isn't same as invalidate(); or invalidate(true);
|
|
|
|
|
Hi,
you did not mention Invalidate() before. It has a completely different purpose: you
call it to tell GDI+ that something needs to be redrawn, e.g. because you have changed
the drawing parameters.
|
|
|
|
|
Sorry for not mentioning invalidate before. But the why should one call to invalidate rather than this.Refresh(); doesn't it redraw the control with the changed parameterize values
|
|
|
|
|
And now you start talking about Refresh; are you going to enumerate all the Control methods
one by one?
I have never used Refresh() and never felt the need to use it; I use Invalidate().
|
|
|
|
|
Hello Luc!
I also prefere using Invalidate(), mainly because of it's higher flexibility (additional parameters).
I think the only reason using Refresh(), which I can think of, would be if more than one GDI changing should be shown in one callstack.
Sometimes for that purpose, I see code where people use Invalidate() + DoEvents(), which I would count as bad practice. Here the usage of Refresh() would be much better.
All the best,
Martin
|
|
|
|
|
Hi Martin,
we agree on the subject of Refresh() and DoEvents().
I seldom use DoEvents, I mainly use it when a dialog gets closed before executing
a (short!) action in order to get the underlying form being redrawn as soon as possible
(so there is no risk of creating nested DoEvent calls).
PS: congrats on your diamond icon!
|
|
|
|
|
There are usually two stages to rendering controls on the form. The first is measurement and the second is rendering. When you add a control to the form it signals that the content has changed and it needs to recalculate everything. Once things have been measured the controls can be redrawn.
This has the downside that it's quite slow when adding lots of controls. What SuspendLayout and ResumeLayout offer is a way to halt re-calculating the layout of the form everytime a control is added, so if you know you're going to be adding a lot of controls you can half the recalculations and then only perform them once when you've finished adding the last one.
So:
this.SuspendLayout();
for (int i = 0; i < 1000; i++)
{
var textBox = new TextBox();
textBox.Size = new Size(120, 24);
textBox.Location = new Point(0, 24 * i);
this.Controls.Add(textBox);
}
this.ResumeLayout();
|
|
|
|
|
The following giving problems (I m using VC# express.) I get the MessageBox but after that, the application hangs up (on me). Can anyone help.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Windows.Forms;
using System.Drawing;
namespace Thread191
{
class Listing191AND192 : Form
{
Label lblInfo2 = new Label();
Button btStart = new Button();
public Listing191AND192()
{
Thread currThread = Thread.CurrentThread;
lblInfo2.Location = new Point(15, 10);
lblInfo2.Size = new Size(300, 100);
lblInfo2.Text = "Hi";
currThread.Name = "Main thread";
btStart.Location = new Point(300, 340);
btStart.Text = "Start";
btStart.Click += new EventHandler(this.StartIt);
this.Text = "Listing191";
this.Controls.Add(lblInfo2);
this.Controls.Add(btStart);
this.Size = new Size(800, 600);
}
void StartIt(object sender, EventArgs e)
{
lblInfo2.Text = "Thread 2 started from " + Thread.CurrentThread.Name + "...\n";
Thread thdTest = new Thread(new ThreadStart(DoIt));
thdTest.Name = "Thread 2";
thdTest.Start();
lblInfo2.Text += Thread.CurrentThread.Name + " sleepin....\n";
Thread.Sleep(2000);
lblInfo2.Text += Thread.CurrentThread.Name + " waking...\n";
thdTest.Join();
lblInfo2.Text += "Thread 2 ended...\n";
}
void DoIt()
{
Thread.Sleep(1000);
MessageBox.Show(Thread.CurrentThread.Name);
lblInfo2.Text += "Hello from " + Thread.CurrentThread.Name + "\n";
}
static void Main(string[] args)
{
Application.Run(new Listing191AND192());
}
}
}
|
|
|
|
|
You can't change UI controls on a thread other than the one that created it. Thus, setting the lblInfo2.Text inside DoIt() is what's causing the problem, since DoIt is being run on a thread other than the one that created the lblInfo2 control.
If you need to do background work and provide updates to the UI in response to some background work progress, have a look at the BackgroundWorker component.
|
|
|
|
|
but isn't thdTest.Join() supposed to make the currentThread wait until Thread 2 finishes with DoIt() method(including wrinting on lblInfo2).
|
|
|
|
|
Join will make the threads join in the "StartIt" method, but the "DoIt" function is running on a different thread.
|
|
|
|
|
I am sorry if I am asking too many questions.
When you say "will make the threads join in the StartIt" which threads are you referring to.
Pl correct me if I am wrong.
What I gathered is that StartIt() is being run by the Main thread and DoIt() is being run by the background thread(Thread 2) and when I use thdTest.Join() the Main Thread stops executing and waits for Thread 2 to finish its job (including writing on lblInfo2) and when Thread 2 is done, then the Main thread picks up from there again and finishes its job.
I have one more question
When I press the button the first thing I see is the MessageBox
Why isn't the label dispalaying the first line of StartIt()
lblInfo2.Text = "Thread 2 started from " + Thread.CurrentThread.Name + "...\n";
before I see the MessageBox
|
|
|
|
|
humayunlalzad wrote: When you say "will make the threads join in the StartIt" which threads are you referring to.
The main UI thread and the thdTest thread.
humayunlalzad wrote: What I gathered is that StartIt() is being run by the Main thread and DoIt() is being run by the background thread(Thread 2) and when I use thdTest.Join() the Main Thread stops executing and waits for Thread 2 to finish its job (including writing on lblInfo2) and when Thread 2 is done, then the Main thread picks up from there again and finishes its job.
That's correct. It will block the UI thread (e.g. freeze the UI) until DoIt() is done executing.
humayunlalzad wrote: Why isn't the label dispalaying the first line of StartIt()
Because the other thread may or may not have set it yet; threads don't execute in any particular order. So if the label was being set in one thread, and looked at in another thread, it's possible that by the time one thread looks at the value, it's not yet set for the other thread.
This is all complex stuff. It gets only more complex once you start having to think about locks to protect variables and data shared between threads.
Here's how you make it simple: don't share memory between threads. That means don't share variables or other data between threads. If another thread needs some data from one thread, make a copy of the data and send him the copy.
|
|
|
|
|
Judah Himango wrote: Thus, setting the lblInfo2.Text inside DoIt() is what's causing the problem
Actually, that won't necessarily cause the problem. Yes, it's a no-no, but often we won't see the actual effects that causes.
I'm more inclined to think it's the MessageBox being shown from the background thread. The MessageBox piggy-backs its message loop on the thread it is called from, and if that's a background thread I have seen all kinds of strange and upsetting behavior from the MessageBox in that situation.
So, my advice is to get rid of the message box. And fix the cross-thread issues. In C# both solutions are trivial.
It has become appallingly obvious that our technology has exceeded our humanity. - Albert Einstein
|
|
|
|
|
Either way, he needs to remove UI code from the background thread.
|
|
|
|
|
Removing the messagebox is not helping, but when I remove the lblInfo2 from the DoIt() method, the problem gets solved.
The question is how do I make DoIt() method write on lblInfo2.
|
|
|
|
|
Hi,
if you need to access a Control from a thread that did not create the Control, then
you need to use Control.InvokeRequired and Control.Invoke()
you can find many examples of this everywhere, including in CP articles; there
is an example at the end of my Sokoban article.
|
|
|
|
|
Use this instead:
lblInfo2.BeginInvoke((ThreadStart)delegate
{
lblInfo2.Text = "whatever";
});
That will invoke the text setter on the correct thread.
If you find yourself doing lots of Control.BeginInvoke or Control.Invoke calls, opt instead to use a BackgroundWorker component. Much simpler and cleaner.
|
|
|
|
|
Thanx guys, this thing is a lil bit tough for me rt now. I will get back to the prob later.
|
|
|
|
|
Ok, continuing on the context of executing reflected code...
Is there any way of adding a web reference in runtime?
Alternatively, what options do I have on invoking a web service without adding the web reference?
Thank you
Gonçalo A.
|
|
|
|
|
Well, you could always create the SOAP request yourself and send it yourself.
|
|
|
|