投稿済み Tue, 14 Jan 2020 14:30:59 GMT 、投稿者 Edward Clarke Community Service Partners Director of Information Technology
Hello,

I have been writing a small program that will collect our computer inventory and store that in DocuWare.  Everything is working great.  I have a question on checking a document in/out.  I want to be able to check a document out and attach the new specs sheet to the old one and check it back in.  I've followed the example https://developer.docuware.com/dotNet_CodeExamples/8949abfb-4386-4e6d-81fc-e0b674ec3fb4.html 

Is there a way to make this sync vs async?  I would want my program to wait while the file is being downloaded from DocuWare so I can merge my spec sheets together and then initiate an upload.
投稿済み Tue, 14 Jan 2020 14:41:58 GMT 、投稿者 Joe Kaufman Bell Laboratories Inc No longer there

Edward,

Some other async examples make the operation become synchronous by asking for the Result of the operation. Consider the example of downloading a document, found here:

https://developer.docuware.com/dotNet_CodeExamples/4354370d-a0ce-42d4-ba94-6dc848ed62c0.html

The main call is an async method, but the Result is summoned, making the program wait:

            var downloadResponse = document.PostToFileDownloadRelationForStreamAsync(
                new FileDownload()
                {
                    TargetFileType = FileDownloadType.Auto
                }).Result;


This gives you back the stream immediately for download.

I am not sure other async routines are written in such a way that this will always work, and async stuff makes my head hurt.

A really quick and dirty way to know if the file is done downloading would be to wait for the file to exist, and then try to lock it for exclusive write. That shouldn't be allowed while the file is still downloading. I have a WaitForFile routine I use for that:
 

        /// <summary>
        /// Like the global VFP function of the same name, this routine waits for a file to appear and not be in use elsewhere (via exclusive write check)
        /// so that the file is known to be available for use and no longer being filled or operated on by any other process.
        /// </summary>
        /// <param name="fileName">The file name to wait for.</param>
        /// <param name="timeout">Milliseconds to wait for the file (forever, by default).</param>
        /// <param name="silent">If true, do not display any information to use, not even if timeout is hit.</param>
        /// <param name="prePauseSeconds">A time to pause (in seconds) before checking for the file, to give the file time to appear regardless of timeout.</param>
        /// <returns>Returns TRUE if file is found and free of other use within timeout period, otherwise FALSE.</returns>
        public static bool WaitForFile(string fileName, int timeout = Int32.MaxValue, bool silent = false, int prePauseSeconds = 0)
        {
            bool fileFound = false;
            int numLoops = 0;
            if (fileName.Length == 0) { return false; }
            if (timeout <= 0)
            {
                // A timeout has been passed in but is zero or less. Assume this is meant to be an infinite wait.
                timeout = Int32.MaxValue;
            }
            if (prePauseSeconds > 0)
            {
                System.Threading.Thread.Sleep(prePauseSeconds * 1000);
            }
            // We can now wait for the file to appear.
            while ((!fileFound) && (numLoops <= timeout))
            {
                if (File.Exists(fileName))
                {
                    fileFound = true;
                }
                else
                {
                    // Wait one second before trying again...
                    System.Threading.Thread.Sleep(1000);
                    Application.DoEvents();
                    if ((numLoops >= 5) && (!silent))
                    {
                        UIFuncs.StartWait("Waiting for file " + fileName + " " + numLoops.ToString() + " times...");
                    }
                    numLoops++;
                }
            }
            // If file not found, then we have timed out.
            if (!fileFound)
            {
                if (!silent) { UIFuncs.StopWait(); }
                return false;
            }
            // If we make it here, we have file, but it might still be growing or in use.
            // Wait until nothing else has it in use.
            numLoops = 0;
            while (FileInUse(fileName) && (numLoops <= timeout))
            {
                // Wait one second before trying again...
                System.Threading.Thread.Sleep(1000);
                Application.DoEvents();
                if ((numLoops >= 5) && (!silent))
                {
                    UIFuncs.StartWait("Waiting for file " + fileName + " " + numLoops.ToString() + " times...");
                }
                numLoops++;
            }
            if (!silent) { UIFuncs.StopWait(); }
            return (numLoops <= timeout);
        }


Never mind the "StartWait" stuff, that is just a popup display I developed to mimic FoxPro's WAIT WINDOW functionality. The above routine calls the method FileInUse, which looks like this:

        /// <summary>
        /// Check to se if a file is in use by trying to open it with exlusive write access (that lock is removed if access is granted).
        /// </summary>
        /// <param name="fileName">The file name to check for being in use.</param>
        /// <returns>Returns TRUE if the file is in use elsewhere, FALSE otherwise.</returns>
        public static bool FileInUse(string fileName)
        {
            bool inUse = true;
            FileStream stream = null;
            try
            {
                FileInfo fi = new FileInfo(fileName);
                stream = fi.Open(FileMode.Open, FileAccess.ReadWrite, FileShare.None);
                inUse = false;
            }
            catch (IOException)
            {
                // File is in use by another process.
                inUse = true;
            }
            finally
            {
                if (stream != null) { stream.Close(); }
            }
            return inUse;
        }


Maybe that would work for you, assuming you are doing this in C#/.NET, of course.

Thanks,
Joe Kaufman




 

フォーラムに投稿するためにはログインが必要です。