非同步委派練習

  • 3914
  • 0
  • C#
  • 2009-12-29

今天無聊自己玩了一下檔案複製

用了FileStream來自行copy

今天無聊自己玩了一下檔案複製

用了FileStream來自行copy


FileStream _reader = new FileStream(filePath, FileMode.Open);
FileStream _writer = new FileStream(DescPath, FileMode.OpenOrCreate, FileAccess.Write);
int _readerCount = 0;
byte[] data;
do
{
    data = new byte[tnsLen];
    _readerCount = _reader.Read(data, 0, tnsLen);
    pro += _readerCount;
    _writer.Write(data, 0, _readerCount);
    label1.Text = pro.ToString();
} while (_readerCount > 0);

F5給他按下去後要移動程式就送我這個畫面

image

然後就要乖乖的等待程式copy完才可以做其他的事情

要解決這種窘境在.NET我想可能用非同步處理會蠻適合的


Action moveFileDelegate = new Action(MoveFile);
moveFileDelegate.BeginInvoke(new AsyncCallback(delegate(IAsyncResult iar)
{
    MessageBox.Show("OK");
}), null);

唉阿,原來另外開一條執行緒在後面並行作業會出現這種錯誤

想想也沒錯

多條執行緒共用同一個control到底的確是不合理

image 

後來摸索了一陣子發現可以由表單本身來控制

把更新label的程式放進delegate後讓from本身來invoke就可以解決此問題

 

不過有時可能不需要不斷的更新control

只需要在完成的時候更新狀態即可

這時可以把MoveFile改為回傳int並呼叫EndInvoke取得結果即可

類似這樣


moveFileDelegate moveDelegate = new moveFileDelegate(this.MoveFile);
moveDelegate.BeginInvoke(delegate(IAsyncResult iar)
{
    AsyncResult ar = (AsyncResult)iar;
    moveFileDelegate mDelegate = (moveFileDelegate)ar.AsyncDelegate;
    int _result = mDelegate.EndInvoke(iar);
    this.Invoke(new UpdateDelegate(UpdateLabel), _result.ToString());
}, null);

 

 

 

 

或是直接將此delegate當作BeginInvoke的最後一個參數傳進AsyncCallback也可以


moveFileDelegate moveDelegate = new moveFileDelegate(this.MoveFile);
moveDelegate.BeginInvoke(delegate(IAsyncResult iar)
{
    moveFileDelegate mDelegate = (moveFileDelegate)iar.AsyncState;
    int _result = mDelegate.EndInvoke(iar);
    this.Invoke(new UpdateDelegate(UpdateLabel), _result.ToString());
}, moveDelegate);

這邊可以發現BeginInvoke的最後一個參數在AsyncCallback中可以由傳入的IAsyncResult的AsyncState取得

所以我也可以改寫為


moveFileDelegate moveDelegate = new moveFileDelegate(this.MoveFile);
moveDelegate.BeginInvoke(delegate(IAsyncResult iar)
{
    AsyncResult ar = (AsyncResult)iar;
    UpdateDelegate mDelegate = (UpdateDelegate)iar.AsyncState;
    this.Invoke(mDelegate, ((moveFileDelegate)ar.AsyncDelegate).EndInvoke(iar).ToString());
}, new UpdateDelegate(UpdateLabel));

經過這次嘗試

相信下次再處理非同步作業時能更得心應手

非同步委派程式設計範例

AsyncFileCopy.zip