views:

255

answers:

2

I have a WCF service which provides a method that creates a file. Sometimes it takes a little while for this file to appear, and other methods which are relying on that file's existence fail if they are called immediately afterward. As a result, I want to check that the file has appeared before proceeding.

In my client class, I can call the service method and then loop until the file has appeared before proceeding - this works perfectly. But if I loop until the file has appeared while still inside the service method, it never finds that the file has been created - unless I call MessageBox.Show() before checking. If I do, it finds it almost immediately, just as if I had called it from the client.

The file definitely exists during the time that the service method is looking for it (Edit: doesn't use File.Exists() as I previously wrote) - so why can't it find it? And why does MessageBox.Show() fix this problem?

I'm assuming it must be a threading issue I don't understand, since it works from outside the service, and works if you call MessageBox.Show() (which blocks the UI thread?) but I'm at a bit of a loss, so any help would be greatly appreciated.

Further info: the service is hosted as a plugin by a running GUI application, if that's relevant to the threading issue. Thanks everyone.

Edit: Here's a version of the code. I didn't post this originally because it uses a third-party library, so I'm not sure how helpful it is:

// The WCF service, in which HasCompiled(name) never
// returns true unless MessageBox.Show() is called:
public void CompileScript(string name)
{      
   // CompileFile outputs a file to disk:
   string debug = NWN2Toolset.NWN2ToolsetMainForm.Compiler.CompileFile(script.Name,GetModuleTempPath());    
   if (debug.Length > 0)
      throw new InvalidDataException("'" + name + "' could not be compiled: " + debug);

   // If the following line is commented out, this method never returns:
   MessageBox.Show("blabla");

   while (!HasCompiled(name));
}

public bool HasCompiled(string name)
{
    NWN2GameModule module = GetModule();
    OEIResRef cResRef = new OEIResRef(name);    
    IResourceEntry entry = module.Repository.FindResource(cResRef,resourceType);
    return entry != null;
}

// The client class, in which HasCompiled(name) returns true almost immediately:
[Test]
public void TestCompilesScript()
{
    service.AddScript(name,scriptContents);
    service.CompileScript(name);

    while (!service.HasCompiled(name)) {
       Console.WriteLine("HasCompiled(" + name+ ") == false.");
    }
    Console.WriteLine("HasCompiled(" + name+ ") == true.");
}
A: 

I don't see your code so I can suggest the following: either don't return the first method until the file created (you might need to change the default timeouts for WCF) Or - only after the first call to the Service returns - loop against the service to see if the file exists.

Not seeing your code, I just can guess - if you are using threads, messagenox.show makes the calls in a certain order (because the system waits for you to dismiss the messagebox).

Dani
Thanks for your answer Dani, but that's the issue - if I tell the service method not to return until the file is found, it NEVER does, even though the file appears. If I tell the client to loop until the file is found, it works correctly, but I really want this to be handled on the service end.
sleepy
A: 

Instead of looping in the client, you could implement a callback instead. There are lots of good examples out there - http://www.google.com/search?q=wcf+callback+example

Christopher Scott