|
Just have the server accept connections in a non-terminating loop. It gets the client Socket connection and spawns a new thread that handles the client communications. This is basically how all the major daemons work.
Also, you may want to look into .NET Remoting and host the remoting object either in a Windows Service or IIS. It's very flexible and very powerful, although it has a pretty steep learning curve if you're not familiar with it. It's definitely worth it, though, if you're developing distributed apps for the .NET Framework.
Microsoft MVP, Visual C#
My Articles
|
|
|
|
|
What is wrong with writing a simple loop without closing the server down?
Or look into the Socket.BeginAccept method if you want something that will perform better.
If you don't kill me you will only make me stronger
That and a cup of coffee will get you 2 cups of coffee
|
|
|
|
|
Yeah, using a timer to start a listener is a REALLY bad idea. This will only try and start a new listener on every timer tick, even if the first one hasn't complete any kind of task. If your timer is launching a new listener every second, or even every minute, ... Uggggh, I don't even want to think about it...
RageInTheMachine9532
|
|
|
|
|
I've got a service that is dependent on some files, and checks for modification of the files (thanks to everyone who helped me understand how to do this). Now that I've got that done, I think it would be nice to be able to have another thread whose sole responsibility is to check the time stamp on these files and reload the data when needed, that way the users don't have to wait while data is reloadedl
My initial thought is to either create another thread and have it sleep or use timers to accomplish this, however I do not know where to place this code in my service. I don't think I would want to put it in the constructor otherwise it would get called whenever anyone made a request, and would result in mutliple threads doing the same thing. Is there anyway to create a new thread when the service starts up (before the initial request) that will do this?
Thanks for your help.
|
|
|
|
|
[edit]Doh. read web service as windows service. Please disregard. [/edit]
The system.timers.Timer is good for this. Add the timer to your service object. Then set the interval and assign the event in your constructor. Then you just need to start and stop the timer in your service start and stop events.
If you need to make absolutely sure that the timer will not be executing after you leave the stop event , you need to do your own thread syncronization, but in most cases you don't need to worry about it.
If you need to schedule multiple jobs look for the scheduled timer CP article I posted a few weeks ago.
If you don't kill me you will only make me stronger
That and a cup of coffee will get you 2 cups of coffee
|
|
|
|
|
I don't remember if you're the same guy I and nother guy were helping before, but look at the Cache class in the .NET Framework. You can access this in your Web Service using the Context property (HttpContext ), which gives you the Cache object. You can add a CacheDependency on that file so that if it changes the cached item is invalidated, so that you read-load the data.
If you look at the documentation for the Cache.Add method, however, you'd notice a CacheItemRemovedCallback parameter (the last parameter). If you didn't want to have the user wait until the data is reloaded, you could add a callback that loads the data as soon as the cache item is invalidated and removed from the cache.
Microsoft MVP, Visual C#
My Articles
|
|
|
|
|
Yes that was me, and thank you for your help. I've got the call back working to where it will remove the cached data on a change. However, in the method that does that, I also try to reload and then re-add the data, but it doesn't re-add.
Here is the method:
<br />
public void TPMDataRemovedCallback(String k, Object v, CacheItemRemovedReason r){<br />
TPMreason = r;<br />
string tpmDataKey = "TPMDATA";<br />
if(onTPMDataRemove == null)<br />
onTPMDataRemove = new CacheItemRemovedCallback (this.TPMDataRemovedCallback);<br />
DateTime NoAbsoluteExpiration = Cache.NoAbsoluteExpiration;<br />
TimeSpan NoSlidingExpiration = Cache.NoSlidingExpiration;<br />
CacheItemPriority Priority = CacheItemPriority.AboveNormal;<br />
Context.Cache.Remove(tpmDataKey);<br />
System.IO.FileInfo fileInfo = new System.IO.FileInfo(tpmFileName);<br />
tpmData = tpm.LoadTPM();<br />
try{<br />
Context.Cache.Add(tpmDataKey,this.tpmData,this.tpmDataCacheDependency,NoAbsoluteExpiration,NoSlidingExpiration,Priority,onTPMDataRemove);<br />
}<br />
catch(System.Exception caught){<br />
Console.WriteLine("Exception == " + caught);<br />
}<br />
}<br />
I don't see an exception get caught, but the cache at Context.Cache[tpmDataKey] doesn't contain anything. What am I doing wrong?
|
|
|
|
|
Did you step through your code and see if this method even gets called? You must first call this method (or a similar one) to load the data into the cache and create the callback.
Microsoft MVP, Visual C#
My Articles
|
|
|
|
|
Yes, I've stepped through the method. It gets called, and there is something on the cache when it gets called. Once that method is called the remove succeeds, as does the loading of the data. However when I call add it doesn't seem to add it to the cache, however upon the next request it sees that there is nothing on the cache, loads the data, and readds it with no problem, and what I don't understand is that I call add then with the same parameters as I do in the RemovedCallback method, only this time it does add it.
|
|
|
|
|
First, you shouldn't call Cache.Remove : the callback is invoked after the item - and remember there could be multiple objects in the cache with different keys - is removed, but you need to be mindful of the key. The following example should work:
private const string KEY1 = "File1.txt";
private const string KEY2 = "File2.txt";
private void CacheFile(string key)
{
if (key == null) throw new ArgumentNullException("key");
if (key.Length == 0) throw new ArgumentException("Invalid key.");
if (Cache[key] == null)
{
string path = Server.MapPath("/docs/" + key);
using (StreamReader reader = new StreamReader(path))
{
Cache.Add(
key,
reader.ReadToEnd(),
new CacheDependency(path),
Cache.NoAbsoluteExpiration,
Cache.NoSlidingExpiration,
CacheItemPriority.AboveNormal,
new CacheItemRemovedCallback(CacheItemRemoved));
}
}
}
private void CacheItemRemoved(string key, object value,
CacheItemRemovedReason reason)
{
if (key == KEY1) CacheFile(KEY1);
else if (key == KEY2) CacheFile(KEY2);
}
public string File1Content
{
get
{
CacheFile(KEY1);
return Cache[KEY1];
}
}
public string File2Content
{
get
{
CacheFile(KEY2);
return Cache[KEY2];
}
}
Microsoft MVP, Visual C#
My Articles
|
|
|
|
|
:-OI'm printing a windows form by looping thru all the controls on the form, but I realized the form needed more than one page to fully print. I know I need to loop thru the controls but not with a 'for' loop. I need to increment each control with a counter of sorts so if I set the hasmorepages, the code will know which control to start with on the next page, but I can't get anything to work. help?
Here's the function that works, but without printing more data on the next page:
private void printDocument1_PrintPage(object sender, System.Drawing.Printing.PrintPageEventArgs e)
{
.......
.......
Graphics g = e.Graphics;
DrawAll(e.Graphics, e);
foreach(Label lbl in panel1.Controls)
{
g.DrawString(lbl.Text, lbl.Font, Brushes.Black, lbl.Bounds.Left*scalex, lbl.Bounds.Top, new StringFormat());
}
}
Nancy
|
|
|
|
|
Use a for loop instead with the current index as a field in your class initialized to 0. then use a for loop like so:
for ( ; i < Controls.Count; i++)
{
Label lbl = Controls[i] as Label;
} Here, i would be a field in your class declared something like:
private int i = 0; FYI, your foreach loop has a major flaw: if a control in the Controls collection is not a Label , an exception would be thrown. This may not be applicable in your application now (if panel1 contains only Label s), but if you ever add anything else your code will throw a cast exception.
Microsoft MVP, Visual C#
My Articles
|
|
|
|
|
thanks....that worked fine. And yes, this form is all labels. But now I have another issue. The first 4 labels on the form were placed on the form during development, and the next bunch are done at runtime. The runtime ones print in order, but the first 4 don't. #2 prints, then #1, then #3, then #4 due to the order I placed them on the form. Is there a way to 'reorder' these so the loop thru the label controls function does what I want it to? I even removed them and recreated them in the order I wanted them, but still they came out wrong. help?
|
|
|
|
|
The designer automatically uses Controls.AddRange to add them. This is in reverse order, so you can re-order them that way, so that they are added as 4, 3, 2, 1. You can also use View->Tab Order and select them in the correct order. This should, IIRC, cause the designer to re-order them as well, though you should double check.
Microsoft MVP, Visual C#
My Articles
|
|
|
|
|
thanks for the fast reply! I did try to reorder by the taborder but it didn't do the trick. But I'll try the addrange. Thanks again!
|
|
|
|
|
My quick and dirty solution (there was no time to develop something more efficient):
1. Find maximum area of whole print
2. split it into printable pages (tiles)
for every page you print:
1. set offset of graphics object into current page
e.Graphics.TranslateTransform(-PrintRectangle.X+e.MarginBounds.Left, -PrintRectangle.Y+e.MarginBounds.Top+this.titleHeight);
2. create "window" for graphics:
e.Graphics.SetClip(PrintRectangle);
3. print EVERYTHING - all the controls you want in any order you want. That's the trick. Clip makes the rest for you
|
|
|
|
|
I accidently screwed up in my OnStart for my service by initializing my main thread before my argument checks and now after uninstalling the service, it is in the state of "Disabling." I've tried rebooting but it won't uninstall fully. I can't reinstall and I can't recompile, so does anyone know what I should do?
Thanks.
----
Xian
|
|
|
|
|
If you can't recompile, that's entirely a different problem, something you need to check, fix, and then recompile.
To get rid of the registry entry for the service, open regedit.exe and drill-down to HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services. Find the key with the name (not the display name) of your service and delete it and reboot.
Microsoft MVP, Visual C#
My Articles
|
|
|
|
|
I couldn't recompile because the .exe was in use by the system. I managed to get it out via safe mode.
Thanks.
----
Xian
|
|
|
|
|
I'm coding a MDI form application. What I really want the form (not the controls it contain) to look like is similar to Office 2003, which reflects the theme the system is using. Could someone give me some help?
Thanks!
|
|
|
|
|
Unless you draw the UI elements with the theme data yourself, it's either all or nothing for applying visual styles.
Microsoft MVP, Visual C#
My Articles
|
|
|
|
|
Also, if you want the Office 2003 look, there are dozens of third-party controls out there (maybe even some free ones, though you get what you pay for often times). Just google.
There's a couple here on CodeProject as well, although - IMO - I don't think they even come close to Office 2003.
Microsoft MVP, Visual C#
My Articles
|
|
|
|
|
I can call EnableVisualStyle to make contained controls to have visula styles. But for the form itself, e.g. border colors, how do I make that happen?
|
|
|
|
|
I have never done this, but from reading I think it is possible. You can create a manifest file using XML to tell your application to use the operating system's style.
The file is placed in the same directory as your project, and is called myProject.exe.manifest
I don't have a link for it at the moment, but I'm sure information will be readily available using google
Hope it helps
|
|
|
|
|
I'm not really sure. I've never tried a callback with a class method before. You'll just have to try it. If you would, please reply whether or not it works.
Microsoft MVP, Visual C#
My Articles
|
|
|
|
|