|
Thanks
|
|
|
|
|
devvvy wrote: My question is, why. Why dotnet ThreadPool is only for quick executions? This makes it kind of useless as if jobs are quick to execute you wouldn't really need to have it placed on a thread in the first place.
This seems counter-intuitive, I had to check what the article writer said for out myself. I hadn't heard this statement before but the answer (at least the one found) makes sense, to the point of being obvious. The ThreadPool has a limited number of threads available, which can recycle once a thread's process has finished. If your process is long-lived, the pool can more easily run out of threads to recycle, reducing performance.
So that leaves the question "Why bother with a ThreadPool at all?", the answer is that creating a Thread is an expensive process: if the process you are running is sort-lived compared to the creation of a new thread (and this is where the "short-lived" comes from) then creating a new thread is a bad choice. The correct choice (assuming you have no other requirements) in this case is to use a ThreadPool, the threads are recycled, reducing the overhead.
Sources:
http://htmlcoderhelper.com/when-to-use-thread-pool-in-c/[^]
http://blogs.msdn.com/b/pedram/archive/2007/08/05/dedicated-thread-or-a-threadpool-thread.aspx?wa=wsignin1.0[^]
Good question, and I've (in the best tradition of South Park) Learned something here today!
|
|
|
|
|
"So that leaves the question "Why bother with a ThreadPool at all?", the answer is that creating a Thread is an expensive process: if the process you are running is sort-lived compared to the creation of a new thread (and this is where the "short-lived" comes from) then creating a new thread is a bad choice. The correct choice (assuming you have no other requirements) in this case is to use a ThreadPool, the threads are recycled, reducing the overhead. "
Yes exactly, if it's short lived, I wouldn't even bother put on a thread. Or have say five to ten short lived operations all put on one Worker thread while UI thread sits around to entertain the users.
But I don't see why the notion of dotnet ThreadPool not meant for long running jobs
If ThreadPool is only for short small jabs, then - yes, creating separate Threads is expensive but you could have just created ONE thread for all/number of short jabs instead of multiple threads or using a ThreadPool at all. Precisely this makes dotnet ThreadPool quite useless if really it's not meant for long running jobs (especially if simple job cancels is not supported)
dev
|
|
|
|
|
"Long lived" is relative (and fuzzy!), and the dev needs to achieve a balance.
Here, you would need to balance off the number of threads created in the pool against their lifespan. At some point the process will be long-lived enough that the threadpool will run out of threads. But you are likely to notice performance problems before you get to this stage (especially in a UI). This problem is allieviated (as Pete's post described) by the fact that we can spin off a fairly large number of threads per pool. Luc's point is also a good one: if you have a few long-lived processes (or I suppose if you spin off new long-lived processes at a slow rate) then the thread pool is an option: the processes won't occupy enough threads to block the addition of all of them. The threadpool might be slightly less efficient than coding the threading yourself in this case, but the loss is small enough not to be a problem in most applications, but you get the benefit of *much* neater code.
In my experience, a suck it and see approach is best for this sort of stuff, if you are still confused, you could try writing a test rig to compare the relative performance of a ThreadPool with processes of differing lengths and addition rates, against managing your own threads.
[Edit 2]
I suggest you read Luc's response, and Pete's too. This doesn't seem to be that much of a problem any more. To be honest, I haven't found any issues with it in the past - but by the time I only really had to use ThreadPools in earnest we were on version 3.0 of the framework.
|
|
|
|
|
|
I use the SmartThreadPool object. I wrote an article that uses it to demonstrate thread pool usage, delegates, and events:
Multithreading, Delegates, and Custom Events[^]
.45 ACP - because shooting twice is just silly ----- "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." - J. Jystad, 2001
|
|
|
|
|
I don't mind a limited number of long-running threads from the ThreadPool. Here is why:
AFAIK the maximum number of threads in the ThreadPool is set right when your app starts, and you have no run-time say in it, as it gets fixed long before your own code starts executing. However a simple experiment with GetMaxThreads() shows the number would currently be 500. (And IIRC there is a way to modify that number at build time). I also read it was raised to 4K on .NET 4.0
The ThreadPool does not create that number of threads right away, it will create them when needed, at a rate of 2 per second (another experiment); i.e. every second (or half second?) it will check whether there are more work items than idle pool threads, and if so, grow the pool by two (or one?). Also, all threads are expensive: creating them takes cycles, and they use a lot of resources, including a 1MB stack each.
If you keep work items short and non-blocking, you'll be able to handle lots of them using just a few threads; that is why one often recommends it: short AND non-blocking.
However the ThreadPool does not care what you do with those threads; the framework as a whole uses some threads as almost all asynchronous events run on them (SerialPort.DataReceived, Timer.Tick, etc). IMO the only thing that matters is not having it run out of threads, so if you want 10 or 50 threads that run for one month, go ahead. If you want hundreds, think again.
Caveat: if your pool threads don't need high-priority, they could still hog the pool, and cause delays in the processing of the asynchronous handler threads; it may be wise to get those handlers operational before loading the pool with low-priority stuff; I do have the impression that some handlers get a dedicated thread from the pool, SerialPort.DataReceived looks like such one. The rationale would be the serial port cannot stall suddenly for 500 msec just because the current population of the pool happens to be fully busy.
Warning: the ThreadPool has strongly evolved in each new .NET release since .NET 1.0; initially it was dumber and much more limited. As a result lot of information about it on the Internet is outdated and confusing.
Some references:
injection and retirement algorithm: http://aviadezra.blogspot.com/2009_04_01_archive.html[^]
async handlers: http://www.perceler.com/articles1.php?art=asyncpool1[^]
Luc Pattyn [Forum Guidelines] [Why QA sucks] [My Articles] Nil Volentibus Arduum
Please use <PRE> tags for code snippets, they preserve indentation, improve readability, and make me actually look at the code.
modified on Friday, December 3, 2010 11:17 PM
|
|
|
|
|
These have all been excellent answers, but one thing that nobody has mentioned is that the initial versions of .NET (1 and 1.1) had an upper limit of 25 threads per process in a single Threadpool. Smart Thread Pool was originally written to work with .NET 1 (and I used it then to overcome the deficiencies).
|
|
|
|
|
Hi,
1. loaded the jpg to picture box (in Size mode as Zoomed).
2. I drawn a rectangle on the picture box and taken the coordinate.
3. opens the jpg in paint and observed the coordinate (where i drawn rectangle on the picture box). when i compare the rectangle coordinate(x and y) with paint coordinate it not the same.
I changed the Size mode to normal and observed that the coordinates are same but the Image size is too large so it display partially. so use zoom size mode property.
Say image with size 2825x3538 and keep the picture box size mode as Normal, the image shows partially in picture box. So i changed picture box mode to zoom (to fit the System screen resolution). and coordinate miss matched when compare it with Normal mode with zoom mode.
How can i achieve the same coordinates.
|
|
|
|
|
That is one of the problems with PictureBox, as soon as you use its features, it becomes hard to add functionality such as getting mouse locations coordinated with image pixels. In such cases I don't use the PB at all, I just use a Panel and paint the content myself (OnPaint handler), so I know exactly what I am doing and what is getting shown where.
|
|
|
|
|
Hi,
In my project I use a ticker to display feeds which get displayed in a scrolling way.
In this we are converting the string to be displayed in BitmapImage and adding it up to the ticker by drawing in it..
Attached is the needed code with the message.:
What i need is the image which we are displaying on clicking on it will open up the URL (which is actually the string now converted to image). i.e. on clicking that scrolling tick will open the displayed URL.
To create bitmap image of the string
private Image CreateBitMapImage(string upText, string downText, int trend)
{
Image trendImage;
ImageAttributes iaTrend;
if (trend > 0 && _ticker.UpTrendImage != null)
{
trendImage = (Image)_ticker.UpTrendImage.Clone();
iaTrend = _ticker.IaUpTrend;
}
else if (trend == 0 && _ticker.NoTrendImage != null)
{
trendImage = (Image)_ticker.NoTrendImage.Clone();
iaTrend = _ticker.IaNoTrend;
}
else
{
trendImage = (Image)_ticker.DownTrendImage.Clone();
iaTrend = _ticker.IaDownTrend;
}
Bitmap b = new Bitmap(1, 1);
Font f = _ticker.Font;
Graphics graphics;
SolidBrush textBrush = new SolidBrush(_ticker.ForeColor);
graphics = Graphics.FromImage(b);
try
{
int width = (int)graphics.MeasureString(upText + downText, f).Width +
_ticker.UpTrendImage.Width;
Rectangle _rect =
new Rectangle((int)graphics.MeasureString(upText + downText, f).Width, 0,
trendImage.Width, _ticker.Height);
b = new Bitmap(b, new Size(width, _ticker.Height));
graphics = Graphics.FromImage(b);
graphics.DrawString(upText, f, textBrush, 0, 0);
graphics.DrawString(downText, f, textBrush,
(int)graphics.MeasureString(upText, f).Width, _ticker.DownTrendRectY);
graphics.DrawImage(trendImage, _rect, 0, 0, trendImage.Width, trendImage.Height,
GraphicsUnit.Pixel, iaTrend);
return b;
}
catch (Exception _ex)
{
throw _ex;
}
finally
{
graphics.Dispose();
textBrush.Dispose();
}
}
to add the item to the ticker panel
public void AddTickerItem(Image img)
{
lock (_tickerItemLock)
{
if (Visible)
{
TickerImageItem _tickImage = new TickerImageItem();
_tickImage.ImageTick = img;
_tickImage.rectF.Y = Padding.Top;
_tickImage.rectF.Height = Height;
_tickImage.rectF.Width = _tickImage.ImageTick.Width;
if (items.Count <= 0)
{
if (startingPositionHasBeenSetAfterHeight == false)
{
_tickImage.rectF.X = Width - 1;
startingPositionHasBeenSetAfterHeight = true;
}
}
else
{
_tickImage.rectF.X = items[items.Count - 1].rectF.X + items[items.Count - 1].rectF.Width;
}
items.Add(_tickImage);
}
}
}
To Draw the Image:
private void Draw(bool bFullImage, Graphics graphicsObj)
{
lock (this)
{
if (graphicsObj != null)
{
RectangleF clipRectF = ClientRectangle;
graphicsObj.Clear(BackColor);
if (bFullImage)
{
if (items.Count > 0 && items[0].rectF.X + items[0].rectF.Width <= 0)
{
lock (_tickerItemLock)
{
items.Remove(items[0]);
}
}
for (int i = 0; i < items.Count; i++)
{
TickerImageItem item = items[i];
if (clipRectF.IntersectsWith(item.rectF))
{
item.rectF.X -= XCoordinateDifference;
graphicsObj.DrawImageUnscaled(item.ImageTick, Rectangle.Ceiling(item.rectF));
}
else
item.rectF.X -= XCoordinateDifference;
}
if (ManagedBackBuffer!=null &&
ManagedBackBuffer.Graphics != null &&
GraphicManager!= null)
ManagedBackBuffer.Render();
}
else if (!bFullImage)
{
graphicsObj.Clear(BackColor);
for (int i = 0; i < items.Count; i++)
{
TickerImageItem item = items[i];
if (item.rectF.X + item.rectF.Width <= 0)
items.Remove(item);
else if (clipRectF.IntersectsWith(item.rectF))
graphicsObj.DrawImageUnscaled(item.ImageTick, Rectangle.Ceiling(item.rectF));
else
break;
}
}
ControlPaint.DrawBorder(graphicsObj, ClientRectangle, BackColor,
ButtonBorderStyle.Solid);
}
}
}
|
|
|
|
|
Just an idea... but when you are adding the Image to the Ticker, why don't you pass along the URL that is associated with the Image and set the "Tag" attribute to the URL. That way when the Image is clicked you can get the URL from that.
|
|
|
|
|
Hai All...
How to use a ListView Control in C#.net Smartdevices for mobile apps
have a sample code is better...
am using this
listview1.items.add("xxx"); like listbox..
is not working...
what is the method to use...
Best Regard's
Mathy's
|
|
|
|
|
You could've surfed CP for existed question.
BTW, It's HERE[^] only.
Regards,
Hiren.
"The more we give of anything, the more we shall get back." - Grace Speare
(you can consider this quote while giving vote also)
Microsoft Dynamics CRM
|
|
|
|
|
|
Are you kidding here ?
Redirecting to the same page is not an answer, I guess.
Regards,
Hiren.
"The more we give of anything, the more we shall get back." - Grace Speare
(you can consider this quote while giving vote also)
Microsoft Dynamics CRM
|
|
|
|
|
It reminds me of the definition of recursive in the dictionary :
recursive adj. See recursive
|
|
|
|
|
5!
Regards,
Hiren.
"The more we give of anything, the more we shall get back." - Grace Speare
(you can consider this quote while giving vote also)
Microsoft Dynamics CRM
|
|
|
|
|
In my smart client application (3.0 Framework) i would like to use Linq.
Whe i tried below code.
string[] names = { "Burke", "Connor", "Frank",
"Everett", "Albert", "George",
"Harris", "David" };
IEnumerable<string> expr = from s in names
where s.Length == 5
orderby s
select s.ToUpper();
foreach (string item in expr) { Console.WriteLine(item); }
This code is throwing an error message
Could not find an implementation of the query pattern for source type 'string[]'. 'Where' not found. Are you missing a reference to 'System.Core.dll' or a using directive for 'System.Linq'?
i have used System.Linq directive in code but unable to add 'System.Core.dll' becuse as it disable. As per the requirement we need to stick on with 3.0 Framework. Any other way to do it.
|
|
|
|
|
Tiger456 wrote: Could not find an implementation of the query pattern for source type 'string[]'. 'Where' not found. Are you missing a reference to 'System.Core.dll' or a using directive for 'System.Linq'?
I think IEnumerable<string> is not supported by LINQ in .NET 3.0 Framework.
You need to implement that functionality manually or initialize query result with var statement.
Click Here for more..[^]
Regards,
Hiren.
"The more we give of anything, the more we shall get back." - Grace Speare
(you can consider this quote while giving vote also)
Microsoft Dynamics CRM
modified on Friday, December 3, 2010 1:28 AM
|
|
|
|
|
Thanks for the response.
But using this method will force the client machine to have .NET 3.5 Framework to run appication right ?
|
|
|
|
|
Yes, For your code you need to upgrade to FW 3.5.
Or you can achieve the same manually using the link I provided.
Regards,
Hiren.
"The more we give of anything, the more we shall get back." - Grace Speare
(you can consider this quote while giving vote also)
Microsoft Dynamics CRM
|
|
|
|
|
So with .NET Framework 2.0 its not possible ?
|
|
|
|
|
Hi Im new to programming, im taking an online class and sometimes it takes a while for someone to get back to me.
We created a notepad program and i want the user of the program to be able to save the file and once the first initial save is saved it wont prompt the user with another pop up asking where to save the file it will automatically save it to the last place it was saved. While writing this i think i answered my other question for the save as haha =^) the Save As would just use the same save click event method.haha
The other is how would i check to see if the user has saved there file prior to closing the program.
private void saveToolStripMenuItem_Click(object sender, EventArgs e)
{
SaveFileDialog saveFile = new SaveFileDialog();
saveFile.Title = "Save File";
saveFile.Filter = "Text File|*.txt|All Files (*.*)|*.*";
DialogResult dr = saveFile.ShowDialog();
if (dr == DialogResult.OK)
{
StreamWriter sw = new System.IO.StreamWriter(saveFile.FileName);
Form activeForm = this.ActiveMdiChild;
if (activeForm != null)
{
TextBox activeText = (TextBox)activeForm.ActiveControl;
if (activeText != null)
{
sw.Write(activeText.Text);
sw.Close();
}
}
}
}
//this is my close, it works but not right if the person has saved their data it will still show the message box because it has text in the text box.
private void exitToolStripMenuItem_Click(object sender, EventArgs e)
{
if (edittextBox.Text != null)
{
MessageBox.Show("Please make sure you save your data!");
}
else
{
Close();
}
}
Thanks for your Help ?=^)
modified on Friday, December 3, 2010 9:01 PM
|
|
|
|
|
All you need to do is store the value of the filename, and check to see if that value is set. If it's not, then display the dialog.
|
|
|
|
|