|
How to create an image list from a resoruce biutmap.
It's along the lines Bitmap.FromResource, and Imagelist.Images.AddStrip, but I'm lacking some syntax here.
Also, I can add a "resource template" to the project, but the "Resource View" tab remains empty. What's that?
If I could find a souvenir / just to prove the world was here [sighist]
|
|
|
|
|
Here is one way to do it. First, make sure your image resource is marked as "Embedded Resource".
Assembly thisAssembly = Assembly.GetAssembly(Type.GetType("Sample.Namespace.SomeForm"));
Stream bmpStream = thisAssembly.GetManifestResourceStream(Sample.Namespace.ResourceName");
Bitmap bmp = new Bitmap(bmpStream);
ImageList.Images.AddString(bmp);
|
|
|
|
|
Hi,
I've been having loads of problems with collections in C#. Up to now, my main class in my program has stored large amounts of data (vertices, polygons etc) in ArrayList's. I'd like to be able to use the Collection Editor from the properties window though, and to do that I realise I need a specific collection for each object. However, I've tried deriving from CollectionBase, and half the function's I've used with ArrayList don't work, then I tried deriving from ArrayList and the program crashed.
I'd really like to just derive from ArrayList and make the collection type specific, can I do this? Or do I have to derive from CollectionBase, and if so, what code must I implement to make it work like ArrayList? I know where to go from there, using custom collection editors, but first I need my custom collection!
Any Ideas?
Dave Kerr
focus_business@hotmail.com
www.focus.esmartweb.com
|
|
|
|
|
Here's all you need (you can obvious add some more methods):
public class MyTypeCollection: System.Collections.CollectionBase
{
public MyTypeCollection(){}
public virtual void Add(MyType value)
{
this.List.Add(value);
}
public virtual MyType this[int index]
{
get {return (MyType) this.List[index];}
set {this.List[index] = value;}
}
public virtual void Remove(MyType value)
{
this.List.Remove(value);
}
}
Nice typed collection with Collection Editor support.
DBHelper - SQL Stored Procedure Wrapper & Typed DataSet Generator for .NET
|
|
|
|
|
Cheers that worked great! I didn't have to change any of the code at all, just replaced 'ArrayList' with 'VertexCollection' and it worked fine.
Thanks very much!
Dave Kerr
focus_business@hotmail.com
www.focus.esmartweb.com
|
|
|
|
|
I am planning a ROM database in C# as hobby project. It may be usefull in retrieving big amounts of non transactional data from CD-ROM or disk file. I know Ms Access is an alternative but as I said it is a hobby project, more Access is not safe enough and brings a lot of overhead.
I may start with saving data into dataset objects, so that when I retrieve it , I can bind it into my win controls right away, anyway I would be retrieving them from database in datasets anyway.
I could save my data into dataset objects and serialize them but they become too big , and retrieving just one line of code would require loading a big file into memory.
Or I can split data and save chunks into numerous dataset objects and putting all these objects in a random access file, than building a hash table / index and saving it into the database. I assume this would minimize schema troubles and shift responsibility to ADO.NET in managing schema in Dataset.
I want your advise on this subject, may be totally different suggestions.
|
|
|
|
|
Is there a way to programmatically move a splitter control? I tried setting it's location, didn't work. I tried setting the size of one of the panels but that didn't work either.
"Outside of a dog, a book is Man’s best friend. And inside of a dog, it’s too dark to read."
-Groucho Marx
|
|
|
|
|
Say you want the panels divided vertically with a splitter control in between.
Dock the panelLeft as Fill
Dock panelRight as Right
Dock the splitter as Right
Programmatically change the size of panelRight with panelRight.Width
This should work.
When you come to a fork in the road, take it! Y. Berra
|
|
|
|
|
Thanks, but it doesn't work.
Form f=new Form();
Panel pf=new Panel();
pf.Dock=DockStyle.Fill;
f.Add(pf);
Splitter s=new Splitter();
s.Dock=DocStyle.Top;
f.Add(s);
Panel pt=new Panel();
pt.Dock=DockStyle.Top;
f.Add(pt);
I have a form with two panels and a splitter inbetween. I can click on the splitter and move it around ok. when I change the size of either or both of the panels, their size does change, but the splitter stays put. If any gap is created it just gets the background color of the Form.
"Outside of a dog, a book is Man’s best friend. And inside of a dog, it’s too dark to read."
-Groucho Marx
|
|
|
|
|
|
Bog wrote
Thanks, but it doesn't work.
Are you using the IDE? If not, editI think) you need to add event handlers to repaint the screen when a panel is resized. (
I used the IDE and it worked fine.
Using the toolbox, add two panels and a splitter. Make sure you add these components to the form and not to one of the other components
Name them pTop, pBottom and s
Set the properties (using the property window) of each as follows:
-----------Dock------BackColor
pTop-------Fill------White
s----------Bottom----Black
pBottom----Bottom----Yellow
When you come to a fork in the road, take it! Y. Berra
|
|
|
|
|
Try this:
using System;
using System.Windows.Forms;
namespace TestSplitter4
{
///
/// Summary description for Splitter4.
///
public class Splitter4 :System.Windows.Forms.Form
{
public Splitter4()
{
Panel pTop = new Panel();
pTop.Dock = DockStyle.Fill;
pTop.BackColor = System.Drawing.Color.White;
Splitter s = new Splitter();
s.Dock = DockStyle.Bottom;
Panel pBottom = new Panel();
pBottom.Dock = DockStyle.Bottom;
pBottom.BackColor = System.Drawing.Color.Aqua;
this.Controls.AddRange(new System.Windows.Forms.Control[] {
pTop,
s,
pBottom
});
}
public static void Main()
{
System.Windows.Forms.Application.Run( new Splitter4 ());
}
}
}
When you come to a fork in the road, take it! Y. Berra
|
|
|
|
|
thank you Donald for all your attemps so far,
This works fine- but what I want to do is programmatically move the splitter.
Like, say the user clicks a button- the splitter changes it's location down 5 pixels, as if the user had clicked it and dragged. I've tried doing this by changing the height of either of the panels that the splitter is splitting- but what happens is, the panel sizes do change, but the splitter stays put.
"Outside of a dog, a book is Man’s best friend. And inside of a dog, it’s too dark to read."
-Groucho Marx
|
|
|
|
|
in an event, change the size of the panel that is not DockStyle.Fill
private void button2_Click(object sender, System.EventArgs e)
{
panel2.Height += 5;
}
When you come to a fork in the road, take it! Y. Berra
|
|
|
|
|
I had a similar problem, and I posted my question to the newsgroup microsoft.public.dotnet.framework.windowsforms.controls on the news server news.microsoft.com
What worked was to change the SplitPostion of the splitter control.
Hope this helps,
Dominique
|
|
|
|
|
I'm writing an app that will do things like display entries from the event log and a few other things. It cycles through 3 event logs, showing errors and warnings in a datagrid.
I was testing out the main app when I happened to have taskmanager (seen end note) open and saw that it was using 40+ meg for a program that was doing nothing really. This got me chasing down why it was using so much memory. So I reduce my program into a smaller set of features, with no add-on dll's and made a small test harness to log memory usage. This showed that on my win2k development server the program ran fine for an hour (<20 meg usage) but in the second hour it hit 40+ meg 3 times. I also ran it on my rc1 .net server and it show memory usage of 180+ meg in 30 mins. I then added in a check call the GC when the memory usage was over a fixed value (~16 meg) and logged whether this was called or not.
The logs showed that on my Win2k server the memory usage continued to climb even though the GC was called every tick of the timer. On my WInXP machine, the GC was called more frequently as time went on, but it stayed around the 16 meg limit.
Has anyone else seen something similar to this? It has frankly driven me up the wall so much I’ve put this project on hold while I write another app and hopefully find a fix for it.
Any one interested in helping or looking at the source, please contact me here or email me ( omega501@hotmail.com ) with a subject of "Request Source" so I don't delete it out of hand
Note: Taskmanager reports memory usage of running apps very badly. It doesn't show how much memory they are currently using, it shows how much it thinks the program will need ( I think). To verify this, open an app (word or similar, something big) and then open taskmanager, select the process tab and find the app you have just run. Select it (so it's easier to find) and then with task manager still open, minimize the app - I did this to MS Word and the memory usage went from 15 meg to 400k instantly - now I make all my .net apps check their own memory
|
|
|
|
|
In my experience, calling GC.Collect() is always a bad idea. It throws of the heuristics the garbage collector uses, and ends up costing you performance because it artificially advances objects into higher generations.
I'd suggest you apply the Allocation Profiler to find out if you've got managed memory problem. This tool is great.
Note that if you've got code using COM interop or P/Invoke, it possible that you've got a classic memory leak. Instead of using the task manager to monitor memory, you can use perfmon. Use the Process object's Virtual Memory, Private Bytes, and Working Set counters on your process, which show overall numbers, then add the ".NET CLR Memory" counter named "# Bytes in all heaps" for you process. If they both grow, your probably holding on to managed memory too long, if just the process ones grow, its unmanaged memory.
Burt Harris
|
|
|
|
|
Thanks. I'll check that out.
The reason I am calling GC explicitly was to see the impact on memory usage, ie. does it free up all the memory and from my logs it's not. In the logs (when graphed) you can easily see the high and low memory usage climbing over time - every time the GC kicks in it doesn't free up as much memory as the previous time. This is with or without calling GC explicitly. The only things I have in the program (outside of labels/textboxes) is the datagrid and a timer. The timer (2 secs) is used to call WMI to check cpu usage, and to read the event logs every 10 secs. Even without these added in, just running the timer to check memory usage and logging the results the memory still gets used in a similar, but smaller, cycle. I am checking the memory usage with this
<br />
CheckMem = Process.GetCurrentProcess();<br />
CurrentMemory = CheckMem.PrivateMemorySize;<br />
Is there a problem with using this method?
To check the cycling behaviour I have avoided creating/destroying objects as much as possible, and I am now just changing the values of the objects
(ie. clearing the datatable that is the source for the datagrid, and programatically adding in new rows as relevent, both the datatable and the datarow are defined "Globally" (to use vb terms, not sure of the c# term)).
I am either explicitly destroying objects when they are finished, or implicitly when the function has finished its job. Where I know I will be using them elsewhere I make them global. This doesn't seem to have stopped the cycling, but it does seem to have slowed it down.
|
|
|
|
|
With a call to Process.GetCurrentProcess() inside a timer event routine, I saw working set growth similar to what you described. The trick is every time you call Process.GetCurrentProcess, it's creating a new object, and it's a fairly heavyweight object...
Try moving the call to Process.GetCurrentProcess() outside of your timer event routine. I made it a member of my Form class and memory growth went away completely. Since its not going to change, you could even make it a static member.
static private Process p = Process.GetCurrentProcess()
private void timer1_Elapsed(object sender, System.Timers.ElapsedEventArgs e) {
label3.Text = DateTime.Now.ToString("hh:mm:ss");
label1.Text = p.PrivateMemorySize.ToString();
label4.Text = p.WorkingSet.ToString();
}
Creating the Process object just once is the real fix for you, but the other thing to point out is that this object implements IDisposable. Whenever an object implements IDisposable, you'll get much better perormance if you manage it's lifetime, and call Dispose() on it when done. This is so important, the C# language added the using statement just for this.
Ignoring the advise of my second paragraph, I left the Process.GetCurrentProcess inside the timer event routine, but wrote it like this:
using (Process p = Process.GetCurrentProcess()) {
label1.Text = p.PrivateMemorySize.ToString();
label4.Text = p.WorkingSet.ToString();
}
Net result: Memory grew a little, but stabilized.
So here's what all this means. Creating a System.Diagnostics.Process directly or indirectly allocates a chunk of unmanaged memory. This unmanaged memory isn't released until either: 1) IDisposable.Dispose is called (implied in my using statement), or 2) the object is garbage collected.
Option 1 (Dispose) is far preferred to option 2, because 2 is far less predictable. But for this paricular case, option 0 (creating the object once and reusing it) is the best.
Burt Harris
|
|
|
|
|
I tried out those suggestions but there still seems to be a problem.
Trying the
<br />
using (Process p = Process.GetCurrentProcess){<br />
...<br />
}<br />
method, I was still showing a similar memory usage. When I tried the
static private Process p = Process.GetCurrentProcess()
method, I was amazed - No memory usage increase was found once the program started. I ran the program overnight and the memory values where the same in the morning as when the program started. Is this saying there isn't a memory leak or that it isn't updating the values properly?
This was using
<br />
static private Process p = Process.GetCurrentProcess();<br />
...<br />
<br />
private void GetCurrentMemory(){<br />
intCurrentMem = p.WorkingSet;<br />
intCurrentMem = p.PrivateMemorySize;<br />
<br />
Both of these returned non-changing values. Am I right in thinking that over a period of 10 hours, there should be some change in memory usage for a program? This program goes out and rotates through 3 event logs (every 10 secs for testing purposes) looking for errors and when an error is found it checks to see if it has already recorded that error in the datatable (I don't want to see 10 entries of "cd-rom has a bad block" or similar, once is enough). This is a fair amount of work that it's doing but using the static process object the memory doesn't change. Changing it to the "Using(...)" format brings back the memory creep though.
|
|
|
|
|
Yup, your right, the static approach is misleading. You can fix it by calling p.Refresh(). The memory isn't exactly static in my simple example, but it stabilizes after a few minutes. I saw the same basic pattern with the using statement.
None the less, the bytes/second allocated seems quite high. I ran the allocaiton profiler on it, and found that the bulk of memory dynamically allocated for my simple test was in System.Diagnostics.ThreadInfo. Again, it looks like the System.Diagnostics.Process class is rather heavyweight for your purpose. I guess it's snapshotting a whole bunch of information you don't need...
You can get working set size from the Environment object, it's lots cheaper, but even with this, I do see an ongoing increase in private bytes by just reading Envrionment.WorkingSet. Interesting... Allocation Profiler says its related to security checks code, that's more what I expect. I leave it running for quite some time and eventually the GC kicks in and trims working set back. I haven't left this running overnight, but I will...
Burt Harris
|
|
|
|
|
I added in the .Refresh() and the memory usage started changing like it used to. Seeing this, I left it running for a few hours and after 7+ hours, the memory usage has a peak of 110 meg (set 5 mins ago), a current memory of 60 meg, and it never dropped below its initial value of 20 meg since the app started.
The main memory usage seems to occur when reading the event log, as when it is checking cpu usage the memory changes a small amount (~100k) but seems stable. It seems to be having problems when reading the event log into a datatable and then displaying that in a datagrid.
It also seems, since I made the Process object static, that a) initial memory usage has jumped (from 10 meg to 20 meg), and that peak memory usage has doubled as well (previously it peaked around 40 - 50 meg, now it's 110 meg).
I am not talking about a lot of data being stored in memory consistently - the datatable has a max of 10 records, and I clear the datatable at the beggining of each loop through the current log (cycling through system, security, application logs every 10 secs for testing purposes).
Is it the Process that is using up so much memory? - I call the p.WorkingSet every 2 secs currently, but now I am only calling the
Refresh(), not creating a new instance of the object. Is there a more "light weight" way of checking the memory usage of a the current app? Maybe calling the Process object is itself causing the high memory usage?
|
|
|
|
|
Welcome to CP Burt! It's always nice to have more people from Microsoft here to answer questions.
So you work in the Speech group huh? Gotta say, I love the .NET Speech SDK. Very nice...even more so that it works with ASP.NET. I send my kudos along to your team.
How did you find out about CP? Was it purely accidental, a coworker mentioning it to you, or was there an internal memo that everybody should monitor what Nick says in his column?
I don't know whether it's just the light but I swear the database server gives me dirty looks everytime I wander past.
-Chris Maunder
Microsoft has reinvented the wheel, this time they made it round.
-Peterchen on VS.NET
|
|
|
|
|
Thank you David. Glad you like the .NET Speech SDK. I can't take much credit for it, I've been working on a related project that hasn't shipped yet, but if you like the SDK, we're probably on the right track.
I found CodeProject tracking down rumors that turned out to be Pavel Zolnikov's Command Prompt Explorer Bar. Now that's some cool software. I'm still studying it, but already I'm impressed.
So there wasn't any sort of all-hands memo, but I will say that there is awareness inside Microsoft as to how important it is we contribute to the developer community. I heard a VP up my reporting chain say he tries to start and end each day solving a customer problem, on message boards or elsewhere. I don't know what forums he haunts, but that's pretty cool.
Topics like this seem like a good place for me. I've got solid server-grade code written in C#, and handling audio data with near real-time requirements. There are a lot of people, (even within Microsoft), who are skeptical of managed code, but my team has taken the plunge, and making it work for our somewhat challenging performance goals hasn't been that hard.
Turning back to the original topic of this thread, what I've learned is that managed memory doesn't mean you won't have memory problems: there are new kinds of memory problems. Understanding the memory allocation behavior your apps is key. With a tools like the allocation profiler, and a little patience, I think most developers will find that solving the new style memory problems (generally performance) a lot easier to diagnose and address than old-style ones (like dangling pointers).
Even with tuning, managed apps will generally use more memory than unmanaged ones, but very high memory consumption indicates a bug in either.
Burt Harris
|
|
|
|
|
Burt Harris (msft) wrote:
I found CodeProject tracking down rumors that turned out to be Pavel Zolnikov's Command Prompt Explorer Bar. Now that's some cool software. I'm still studying it, but already I'm impressed.
I think everybody loves that thing! I use it all the time. It's worth the extra few seconds it takes to start up cmd.exe and put it in the window.
Burt Harris (msft) wrote:
So there wasn't any sort of all-hands memo, but I will say that there is awareness inside Microsoft as to how important it is we contribute to the developer community. I heard a VP up my reporting chain say he tries to start and end each day solving a customer problem, on message boards or elsewhere. I don't know what forums he haunts, but that's pretty cool.
That's really cool. I'm glad to know that most of you guys really are concerned with our comments. I for one, laugh at people who say that Microsoft is a huge corporate giant that doesn't care. And I can do that because of people like you, your VP, Eric Gunnerson, and Nick Hodapp. I must say kudos to you guys. It's a lot easier to solve a problem when someone with the inside scoop comes along to help you out.
I don't know whether it's just the light but I swear the database server gives me dirty looks everytime I wander past.
-Chris Maunder
Microsoft has reinvented the wheel, this time they made it round.
-Peterchen on VS.NET
|
|
|
|
|