多线程通信之AutoResetEvent

AutoResetEvent允许线程通过发信号互相通信。通常,当线程需要独占访问资源时使用该类(AutoResetEvent是操作单个线程的)。
线程通过调用 AutoResetEvent 上的 WaitOne 来等待信号。 如果 AutoResetEvent 为非终止状态,则线程会被阻止,并等待当前控制资源的线程通过调用 Set 来通知资源可用。
调用 Set 向 AutoResetEvent 发信号以释放等待线程。 AutoResetEvent 将保持终止状态,直到一个正在等待的线程被释放,然后自动返回非终止状态。 如果没有任何线程在等待,则状态将无限期地保持为终止状态。
如果当 AutoResetEvent 为终止状态时线程调用 WaitOne,则线程不会被阻止。 AutoResetEvent 将立即释放线程并返回到非终止状态。
例子:在上海坐地铁,检票口有个刷卡的通道,一次只能一个人刷卡后通过,而我过后,它又是关闭的,另一个人又得再刷卡.一次操作,只有一个事件,这时就是非终止状态,一般是用来同步访问资源.

Set方法将事件状态设置为终止状态,允许一个或多个等待线程继续;
Reset方法将事件状态设置为非终止状态,导致线程阻止;
WaitOne阻止当前线程,直到当前线程的WaitHandler收到事件信号。

可以通过构造函数的参数值来决定其初始状态,若为true则事件为终止状态从而使线程为非阻塞状态,为false则线程为阻塞状态。

如果某个线程调用WaitOne方法,则当事件状态为终止状态时,该线程会得到信号,继续向下执行。

AutoResetEvent.WaitOne()每次只允许一个线程进入,当某个线程得到信号后,AutoResetEvent会自动又将信号置为不发送状态,则其他调用WaitOne的线程只有继续等待,也就是说AutoResetEvent一次只唤醒一个线程;
...
public void init() {
isActive = true;

    Thread t = new Thread (work);
    t.Start ();
}

public void work() {
    DownloadMgr mgr = DownloadMgr.getInstance ();

    while (mgr.isActive) {
        if (!mgr.trigger ()) {
            Thread.Sleep (3000);
        }
    }
}

public bool trigger () {
    DownloadFileInfo data = null;
    bool empty = true;

    lock(syncLock) {
        if (list.Count > 0) {
            data = list [0];
            list.RemoveAt (0);

            empty = false;
        }
    }

    if (!empty) {
        doDownload (data);
    }

    return !empty;
}

private void doDownload(DownloadFileInfo data) {
    while (_workingCount >= _MaxCount) {
        waitHandle.WaitOne();
    }
    _workingCount++;

    OtkClient.DownloadFile (data);
}

public void addDownload(string fileURL, string savePath, DownloadCallback succeedCallback, DownloadCallback failedCallback, LuaFunction progressCallback) {
    lock (syncLock) {
        DownloadFileInfo info = new DownloadFileInfo ();
        info.fileURL = fileURL;
        info.realFilePath = savePath;

        // 先下载到一个临时文件,然后再复制到正确路径
        info.tmpFilePath = savePath + GameController.getInstance().getMilliseconds();

        info.succeedCallback = ()=>{
            succeedCallback();

            onDownloadOver();
        };
        info.failedCallback = () => {
            failedCallback ();

            onDownloadOver();
        };
        info.progressCallback = progressCallback;

        list.Add (info);
    }
}

private void onDownloadOver() {
    _workingCount--;

    waitHandle.Set();
}

}
...

你可能感兴趣的:(多线程通信之AutoResetEvent)