|
I figured it out after I found a reference that states: when passing a RectangleF as one of the parameters, DrawString automatically wraps the text inside the destination's bounding rectangle.
So I changed by method call to:
RectangleF cardBox = new RectangleF( rich.Bounds.X + 5, rich.Bounds.Y + 5, rich.Bounds.Width - 5, rich.Bounds.Height - 5 );
g.DrawString( rich.Text, rich.Font, Brushes.Black, cardBox, frmt );
The 'cardBox' rectangle is deflated by 5 pixels for padding. I also included a StringFormat to center the text on the card.
Mark
|
|
|
|
|
you want -10 to center, not -5, and even that is just an approximation as it will paint flush left.
to really center, you need to use Graphics.MeasureString to find actual width, then adjust Left (and maybe Top) while keeping the original Width and Height.
|
|
|
|
|
Hi,
Just a quick question for people. How do I pass TextWriter through a function?
My main opens a TextWriter called LogWritter.
I want to create a function which has this log file passed to it so I can write to it from within this seperate function. I want my program to look like this:
Main()
{
TextWriter LogWriter = new StreamWriter(LogLocation);
for (i=0... etc loop
{
MyFunction(LogWriter)
}
}
</per>
<pre>
MyFunction(TextWriter LogWriter)
{
LogWriter.WriteLine("Hello World")
}
I would expect Hello World to be written as many times as looped in LogLocation. How come this does not appear to work? When I run this the file in LogLocation remains blank.
Many Thanks
Steve
|
|
|
|
|
You don't flush the text writer or close it. If you check the file before the writer is garbage collected, you can't be certain what will be in the file.
This should fix your problem:
Main()
{
using (TextWriter LogWriter = new StreamWriter(LogLocation))
{
for (i=0... etc loop
{
MyFunction(LogWriter)
}
}
}
MyFunction(TextWriter LogWriter)
{
LogWriter.WriteLine("Hello World")
LogWriter.Flush()
}
Dalek Dave: There are many words that some find offensive, Homosexuality, Alcoholism, Religion, Visual Basic, Manchester United, Butter.
Pete o'Hanlon: If it wasn't insulting tools, I'd say you were dumber than a bag of spanners.
|
|
|
|
|
Awesome! That does the trick! Thank you very much.
Do I have to remember to flush the buffer after everytime I write something, or just at the end of each loop?
Many Thanks
Steve
|
|
|
|
|
Steve-Co wrote: Do I have to remember to flush the buffer after everytime I write something, or just at the end of each loop?
Wherever suits really. The buffer builds up in memory until a flush is performed. so if you sre writing a lot of stuff it will eat memory. Also, you might want to write regularly for robsuness purposes (e.g. application crashes and an unflushed audit log loses vital information). I tend to flush regularly .
You should always close the stream (in my code the using achieves this) this also flushes.
If you are writing a logging block, Google Log4Net, it is free and covers a lot of logging tasks, unless you are doing this out of interest or are required to implement your own.
Dalek Dave: There are many words that some find offensive, Homosexuality, Alcoholism, Religion, Visual Basic, Manchester United, Butter.
Pete o'Hanlon: If it wasn't insulting tools, I'd say you were dumber than a bag of spanners.
|
|
|
|
|
It depends, if you are writing all the rows at once, you don't need to flush the writer after each write.
On the other hand, if time is passing between each write, you might want to flush the writer giving the user the possibility to see the log file updating realtime.
If you look to some existing logging framework, you see they have an auto-flush option used to control this behavior.
|
|
|
|
|
Try something like this:
TextWriter LogWriter = null;
public void Main()
{
string LogLocation = @"c:\bin\test.log";
LogWriter = new StreamWriter(LogLocation);
for (int _loop = 0; _loop <= 10; _loop++)
{
MyWriter(LogWriter);
}
LogWriter.Flush();
LogWriter.Close();
}
void MyWriter(TextWriter LogWriter)
{
LogWriter.WriteLine("Hello World");
}
me, me, me
"The dinosaurs became extinct because they didn't have a space program. And if we become extinct because we don't have a space program, it'll serve us right!"
Larry Niven
|
|
|
|
|
your code looks fine, except flushing something right before closing it does not make much sense, every close implies a flush. Flush() is meant to be called when you do not intend to close right away, it is kind of a restore point, making sure the data so far gets output.
|
|
|
|
|
Thanks but it was just a simplistic example.
me, me, me
"The dinosaurs became extinct because they didn't have a space program. And if we become extinct because we don't have a space program, it'll serve us right!"
Larry Niven
|
|
|
|
|
Thanks for all your advice. Just using the "using", in the first reponse, implements the flush() and close() and it now works as expected now.
Many Thanks
|
|
|
|
|
Hi,
I have an event registered to receive serial port data. to my understanding this is done in a separate thread than the one registered in. Ok now in my serial port data receive event i take the data generate a message and send to a windows message queue. method to implement sending is a static method in a separate class library.
Problems.
When data is received and the static method is called , suddenly a new thread is generated and it keeps on doing that for each data received even though i havent spawned any new thread. i have taken the method from the library pasted it in my current working class scope and the same thing happens.
but if i write the sending stuff in the event itself this doesnot happen and everything works just fine.
So to my understanding a different thread is accessing a different thread so there could be safety issues or something else. Do i need to make some kind of asynchronous calls or any other solution please.
I want the function to remain in class library outside the scope of this class.
Can anyone help me with this matter.
Thank you!!! in advance.
|
|
|
|
|
Hi,
the DataReceived and ErrorReceived events fire on a ThreadPool thread. AFAIK it is always one and the same thread for any given serial port. You do not need to create yet another thread to handle the data; when you want to access some data structures (maybe a collection), you would need thread synchronization, most likely a simple lock would suffice. And when you would like to access some GUI Controls, you would need a Control.InvokeRequired/Control.Invoke pattern.
static is irrelevant in this context.
if your code keeps creating new threads, that does not make sense.
you do not need to add any asynchronous calls.
if you want specific help, post specific information and (part of) actual code.
|
|
|
|
|
I understand your point clearly... this code is a part of a windows service... Please find the code below.
This is the serial data received event(part of a running windows service).
Where i just called a static event and passing in some event arguments (custom made)
private void serialCnn_DataReceived(object sender, SerialDataReceivedEventArgs e)
{
try
{
EventReporter.SendData(new SendSerialDataArguments
{
SerialPortName = ((SerialPort)sender).PortName,
Source = Entity.SerialServer,
Destination = Entity.DataProcessor,
SourceServer = Entity.SerialServer,
TransmittedDataType = TransmittedDataType.RawProcessed,
Data = new Message(((SerialPort)sender).ReadTo("\r"))
});
}
catch (Exception ex)
{
this.MiscFunctions.WriteToLog(Entity.SerialServer, ex);
}
}
The method called is a static method in a class library reference by this windows service.
The method is:
public static void SendData(SendSerialDataArguments args)
{
try
{
args.Data.Formatter = new BinaryMessageFormatter();
args.Data.Label = ((int)args.Source).ToString() + ":" + ((int)args.Destination).ToString()
+ ":" + ((int)TransmittedMessageType.Data).ToString() + ":" + ((int)args.SourceServer).ToString()
+ ":" + ((int)args.TransmittedDataType).ToString() + ":" + args.SerialPortName;
args.Data.Recoverable = true;
switch (args.Destination)
{
case Entity.Application:
{
msgQPL.Send(args.Data, MessageQueueTransactionType.Single);
}
break;
case Entity.DataProcessor:
{
msgQCL.Send(args.Data, MessageQueueTransactionType.Single);
}
break;
}
}
catch (Exception ex)
{
MiscFunctions.WriteToLog(Entity.EventReporter, ex);
}
}
The msgqueue objects msgqcl and msgqpl are also static and defined elsewhere in the same class as static.
I even changed the method to not a static one and disposed msq object in it but same result.
any further help!!!
|
|
|
|
|
Hi,
1. Threading
I don't see anything about threading at all. Hence I don't think there would be a threading problem.
2. static
Your explanation isn't clear at all; there are two simple schemes regarding static:
A. don't make anything static (possible exception: a method that does not need any class member data could be made static to enforce that)
B. make everything static (that is impossible if you need two or more of something)
If you try to have a half-static approach, every method declared static can only access class members that are static themselves. That is all that is to it.
|
|
|
|
|
Again i understand ure explanation clearly...
There isn't suppose to be any new thread spawned and doing something static doesn't matter either.
But the thing odd is that if i do the same thing(i.e. sending messages to msq in the serial port data received event, this doesn't result in the continuous spawning of new threads.
Nothing seems to add up y new threads are created if i just take the same code and place it in a class library rather than in the serialport data received event.
i have commented the code in the serial port data received event. which i executed instead of the event reporter event and everything went f9. May be there is some problem with this serial port data received thread accessing methods outside its thread.perhaps.
again any further solutions invited.
|
|
|
|
|
Hi,
Is there any chance that you are blocking the serial port data received thread? If this were to happen I assume that subsequent events would have to use a different thread.
Alan.
|
|
|
|
|
That will surely do that... but in the debug mode i can see my control returning to the data received event, if that can be checked this way.
+ enlighten me like async functions which uses the threadpool limited to 25 threads, saturating on 25 threads if used. If according to u it uses the thread pool and if there is a a cap on it it must also saturate. but i have seen the threads go up to 500 and keeps on increasing.
+ i think so i should use an async function to do the rest of the work (sending to msgq). if it ties up the thread that would be freed perhaps and it may not require another thread for next data received event. perhaps.
Again what do u say...
Really thanks on answering all of my questions
grateful..
|
|
|
|
|
Found the solution....
I tried everything even async method calls. nothing got me to the solution. finally i just mistakenly changed the serialport.ReadTo("\r") to ReadExisting() and it solved the thread problem.
Dont know till now y That ReadTo problem acted like that .
:P
|
|
|
|
|
I have the following method that attempts to create a thumbnail image if it is missing. I get an out of memory exeception on the marked line
public static void CreateThumbs(DataTable oTable, string sImageFolder)
{
try
{
string sThumbFolder = System.IO.Path.Combine(sImageFolder, "Thumbs");
string sUploadFolder = System.IO.Path.Combine(sImageFolder, "Uploads");
string sThumb, sImage;
System.IO.FileInfo oImageFile;
System.IO.FileInfo oThumbFile;
if (oTable.Columns.Contains("Thumb"))
{
foreach (DataRow oRow in oTable.Rows)
{
sThumb = System.IO.Path.Combine(sThumbFolder, oRow["FileName"].ToString());
sImage = System.IO.Path.Combine(sUploadFolder, oRow["FileName"].ToString());
oThumbFile = new System.IO.FileInfo(sThumb);
oImageFile = new System.IO.FileInfo(sImage);
if (!oThumbFile.Exists && oImageFile.Exists)
{
>>>>> error on this line >>>> using (System.Drawing.Image oImage = System.Drawing.Image.FromFile(sImage))
{
using (System.Drawing.Image oThumbnailImage = oImage.GetThumbnailImage(64, 64, new System.Drawing.Image.GetThumbnailImageAbort(ThumbnailCallback), IntPtr.Zero))
{
oThumbnailImage.Save(sThumb, System.Drawing.Imaging.ImageFormat.Jpeg);
}
}
}
}
}
}
catch (Exception)
{ throw; }
}
I can't actually be out of memory I.m on a win7 64 with 8g memory and a fresh reboot!
Never underestimate the power of human stupidity
RAH
|
|
|
|
|
Hi Mycroft,
I suggest you add some code to see exactly what image file is causing the problem. I'm pretty sure it will always be the same, no matter how many images you have. A real out-of-memory situation would typically fluctuate a bit.
The problem you are likely to have is either a corrupted file, or an image format not supported by .NET;
the documentation on Image.FromFile() hides this little gem:
OutOfMemoryException:
The file does not have a valid image format.
-or-
GDI+ does not support the pixel format of the file.
|
|
|
|
|
That's a real gem. I guess I received some OutOfMemoryExceptions in other contexts where such an exception was simply not possible. Maybe the programmer wants to tell as something different, like "the appropriate name for that exception is no more in my memory". Let's call it an AlzheimerException then.
|
|
|
|
|
There is a general problem with GDI+ and exceptions; most often you get a "General GDI+ exception" and are at a loss (try debugging a failing Image.Save operation).
In this particular situation, he got what is masqueraded as an OOM but actually is something quite different.
|
|
|
|
|
Seems reasonable, the image files probably originated on a mac anyway so they could be anything. Turns out there are a huge number of records with no image file so the first one will be to delete records with missing files and delete files not in the database then test each one for corruption, then turn the rest into thumbs. I hate graphics.
Never underestimate the power of human stupidity
RAH
|
|
|
|
|
I don't know about deleting records, you might as well amend your code to skip null filenames. Afterward, a simple try-catch could be all it takes to identify a sporadic bad image file; unless you are filling the database with "images" that aren't "Images" as supported by .NET
Mycroft Holmes wrote: the image files probably originated on a mac
If and when multiple files cause problems, you'll have to find a way around that. Any idea what the original format, or file extension used to be (assuming they had one, Mac has different concepts).
If .NET can't read any of your images, your database will not be worth much, will it?
FYI: I hope you did carefully read the remarks[^], image file may indeed contain thumbnail information of insufficient quality for your purpose.
Mycroft Holmes wrote: I hate graphics
I don't, it is an interesting, evolving and challenging domain. There are several standards, and some special cases. As always.
|
|
|
|