none
背景作業?? RRS feed

  • 問題

  • 請問使用system.IO複製檔案的時候,如何使動作背景執行不會使畫面停頓,並將進度顯示到progressBar,好像可以用backgroundWorker做到,可是不知該如何使用.

    2007年7月4日 上午 06:14

解答

  • 這裡有個簡單的範例:

    http://msdn2.microsoft.com/zh-tw/library/hybbz6ke(VS.80).aspx

     

    簡單的來說就是:

    • 設定 DoWork 委派,這個委派會指向你要做長時間工作的函式(例如檔案複製)。
    • 設定 WorkerReportsProgress 屬性為 true,否則 ReportProgress() 會失效。
    • 在長時間工作的函式中,使用 ReportProgress() 來引發 ProgressChanged 事件
    • 處理 ProgressChanged 事件,以更新 ProgressBar 的值。
    • 在長時間工作的函式的最後,設定 e.Result= true
    • 如果你想要在完成後再做一些事,可處理 RunWorkerCompleted 事件。
    • 呼叫 RunWorkerAsync() 來啟動作業。

    以上所述之事件,方法和屬性,都是 BackgroundWorker 元件中的。

    2007年7月4日 上午 06:45
    版主

所有回覆

  • 這裡有個簡單的範例:

    http://msdn2.microsoft.com/zh-tw/library/hybbz6ke(VS.80).aspx

     

    簡單的來說就是:

    • 設定 DoWork 委派,這個委派會指向你要做長時間工作的函式(例如檔案複製)。
    • 設定 WorkerReportsProgress 屬性為 true,否則 ReportProgress() 會失效。
    • 在長時間工作的函式中,使用 ReportProgress() 來引發 ProgressChanged 事件
    • 處理 ProgressChanged 事件,以更新 ProgressBar 的值。
    • 在長時間工作的函式的最後,設定 e.Result= true
    • 如果你想要在完成後再做一些事,可處理 RunWorkerCompleted 事件。
    • 呼叫 RunWorkerAsync() 來啟動作業。

    以上所述之事件,方法和屬性,都是 BackgroundWorker 元件中的。

    2007年7月4日 上午 06:45
    版主
  • 關於

    "處理 ProgressChanged 事件,以更新 ProgressBar 的值。"

    小弟有一點不懂ProgressBar的值是否需要我自己設定而不能從ReportProgress() 抓取嗎?

    這樣是否有辦法顯示單檔的複製進度??

     

    麻煩大大@@

    2007年7月4日 上午 07:24
  • ReportProgress() 會引發 ProgressChanged 事件,

    並且把 ReportProgress() 的值當做事件參數傳給 ProgressChanged 事件。

     

    你自己不可以直接在 DoWork 中的函式更新控制項,因為那二個並不是在同一個執行緒中。

    ReportProgress() 和 ProgressChanged 事件內部有實作跨執行緒的交換,幫你把這件事做掉。

    2007年7月4日 上午 07:34
    版主
  • 這樣有辦法顯示單檔複製進度嗎??
    2007年7月4日 下午 12:28
  • 你要實作機制才行啊 ...

     

    你可以用 FileStream 讀出位元組,然後在寫入檔案時,把進度顯示在進度列就好了 .

    用 API 處理也行:CopyFileEx()

    2007年7月4日 下午 01:08
    版主
  • 感謝大大耐心指導可是我還是有點霧煞煞的

    請問是否有顯示單檔複製進度的程式範例可以給我看看

    小弟是學生純粹因為興趣學習沒有老師教只有幾本書所以教不懂還希望大大見諒......

    2007年7月4日 下午 03:16
  • 因為"檔案龐大"複製時會長時間停頓怕使用者會誤以為當機所以希望做到以下功能:

     

    表單上有兩個PorgressBar一個顯示總複製進度 一個顯示單個檔案的複製進度

    FileStream只能抓到該檔案的總位元組但抓不到目前程式已經複製的多少位為組

    目前小弟已經做到了第一個PorgressBar(總進度)的功能

    但是單個檔案的功能做不出來

    2007年7月5日 下午 03:44
  • 你那篇文章有沒有看?

    還是只看文字沒看程式碼?

     

    (以下為該篇文章所附程式碼) 

    Code Snippet
    public sealed class FileRoutines
    {
        public static void CopyFile(FileInfo source, FileInfo destination)
        {
            CopyFile(source, destination, CopyFileOptions.None);
        }

        public static void CopyFile(FileInfo source, FileInfo destination,
            CopyFileOptions options)
        {
            CopyFile(source, destination, options, null);
        }

        public static void CopyFile(FileInfo source, FileInfo destination,
            CopyFileOptions options, CopyFileCallback callback)
        {
            CopyFile(source, destination, options, callback, null);
        }

        public static void CopyFile(FileInfo source, FileInfo destination,
            CopyFileOptions options, CopyFileCallback callback, object state)
        {
            if (source == null) throw new ArgumentNullException("source");
            if (destination == null)
                throw new ArgumentNullException("destination");
            if ((options & ~CopyFileOptions.All) != 0)
                throw new ArgumentOutOfRangeException("options");

            new FileIOPermission(
                FileIOPermissionAccess.Read, source.FullName).Demand();
            new FileIOPermission(
                FileIOPermissionAccess.Write, destination.FullName).Demand();

            CopyProgressRoutine cpr = callback == null ?
                null : new CopyProgressRoutine(new CopyProgressData(
                    source, destination, callback, state).CallbackHandler);

            bool cancel = false;
            if (!CopyFileEx(source.FullName, destination.FullName, cpr,
                IntPtr.Zero, ref cancel, (int)options))
            {
                throw new IOException(new Win32Exception().Message);
            }
        }

        private class CopyProgressData
        {
            private FileInfo _source = null;
            private FileInfo _destination = null;
            private CopyFileCallback _callback = null;
            private object _state = null;

            public CopyProgressData(FileInfo source, FileInfo destination,
                CopyFileCallback callback, object state)
            {
                _source = source;
                _destination = destination;
                _callback = callback;
                _state = state;
            }

            public int CallbackHandler(
                long totalFileSize, long totalBytesTransferred,
                long streamSize, long streamBytesTransferred,
                int streamNumber, int callbackReason,
                IntPtr sourceFile, IntPtr destinationFile, IntPtr data)
            {
                return (int)_callback(_source, _destination, _state,
                    totalFileSize, totalBytesTransferred);
            }
        }

        private delegate int CopyProgressRoutine(
            long totalFileSize, long TotalBytesTransferred, long streamSize,
            long streamBytesTransferred, int streamNumber, int callbackReason,
            IntPtr sourceFile, IntPtr destinationFile, IntPtr data);

           
        [SuppressUnmanagedCodeSecurity]
        [DllImport("Kernel32.dll", CharSet=CharSet.Auto, SetLastError=true)]
        private static extern bool CopyFileEx(
            string lpExistingFileName, string lpNewFileName,
            CopyProgressRoutine lpProgressRoutine,
            IntPtr lpData, ref bool pbCancel, int dwCopyFlags);
    }

    public delegate CopyFileCallbackAction CopyFileCallback(
        FileInfo source, FileInfo destination, object state,
        long totalFileSize, long totalBytesTransferred);

    public enum CopyFileCallbackAction
    {
        Continue = 0,
        Cancel = 1,
        Stop = 2,
        Quiet = 3
    }

    [Flags]
    public enum CopyFileOptions
    {
        None = 0x0,
        FailIfDestinationExists = 0x1,
        Restartable = 0x2,
        AllowDecryptedDestination = 0x8,
        All = FailIfDestinationExists | Restartable | AllowDecryptedDestination
    }

     


    2007年7月6日 上午 02:29
    版主