瀏覽標籤:

C#

[C#][TPL] 自定義 TaskScheuler 管理執行續

最近利用 Task 撰寫非同步的程式時碰到了許多未釐清的用法,這邊筆記一下自定義  TaskScheuler 的方法。

public class StaticThreadTaskScheduler : TaskScheduler, IDisposable
{
    private readonly List<Thread> _threads = new List<Thread>();
    private readonly BlockingCollection<Task> _tasks = new BlockingCollection<Task>();
    private readonly AutoResetEvent _lockObj = new AutoResetEvent(true);

    public new int MaximumConcurrencyLevel { get; private set; }

    public StaticThreadTaskScheduler() : this(Environment.ProcessorCount) { }

    public StaticThreadTaskScheduler(int maximumConcurrencyLevel)
    {
        MaximumConcurrencyLevel = maximumConcurrencyLevel;
        initalize();
    }

    protected override IEnumerable<Task> GetScheduledTasks()
    {
        return _tasks;
    }

    protected override void QueueTask(Task task)
    {
        if (task != null)
        {
            _lockObj.WaitOne();
            _tasks.Add(task);
            _lockObj.Set();
        }
    }

    protected override bool TryExecuteTaskInline(Task task, bool taskWasPreviouslyQueued)
    {
        return false;
    }

    private void initalize()
    {
        for (int i = 0; i < MaximumConcurrencyLevel; i++)
        {
            Thread thread = new Thread(execute);
            thread.IsBackground = true;
            thread.Start();
            _threads.Add(thread);
        }
    }

    private void execute()
    {
        foreach (var task in _tasks.GetConsumingEnumerable())
        {
            TryExecuteTask(task);
        }
    }

    #region IDisposable Support

    private bool _disposedValue = false;

    protected virtual void Dispose(bool disposing)
    {
        if (!_disposedValue)
        {
            if (disposing)
            {
                _lockObj.WaitOne();
                foreach (var thread in _threads)
                {
                    thread.Join();
                }
                _threads.Clear();
                _tasks.Dispose();
                _lockObj.Dispose();
            }
            _disposedValue = true;
        }
    }

    public void Dispose()
    {
        Dispose(true);
    }

    #endregion
}

為了測試 StaticThreadTaskScheduler 是否真的如預期,我寫了一小段 Testing Code 去驗證。

class Program
{
    static StaticThreadTaskScheduler _scheduler = new StaticThreadTaskScheduler(1);
    static void Main(string[] args)
    {
        foreach (var item in Enumerable.Range(1, 100))
        {
            Task.Factory
                .StartNew(() =>
                    WorkingAsync(item),
                    CancellationToken.None,
                    TaskCreationOptions.None,
                    _scheduler)
                .Unwrap();
        }
        Console.ReadKey();
        _scheduler.Dispose();
        Console.ReadKey();
    }

    static async Task WorkingAsync(int i)
    {
        while (true)
        {
            Console.WriteLine($"Thread ID: {Thread.CurrentThread.ManagedThreadId}, Working ID: {i}");
            await
                Task.Factory
                    .StartNew(async () =>
                        {
                            await Task.Delay(1000);
                            Console.WriteLine($"Thread ID: {Thread.CurrentThread.ManagedThreadId}, Sub Working ID: {i}");
                        },
                        CancellationToken.None,
                        TaskCreationOptions.None,
                        _scheduler)
                    .Unwrap();
        }
    }
}

結果如下:

       

[C#][MSSQL] 連線結束後 Temp Table 沒有自動釋放 !?

上次 [C#] SQL 資料庫 Connection Pool 連線池觀念釐清 有提到可以開啟 Connection Pool 來減少開啟連線的效能耗損,但最近發現有 Stored Procedure 執行後沒有手動 Drop Temp Table,而 .NET 又將連線丟回 Pool 裡面造成 Temp Table 沒有被正常釋放的問題,下面來測試看看是不是真的會有這種情況發生。 閱讀更多

       

[C#] Registrykey 登錄機碼的新增、修改、刪除、讀取

寫 Windows 應用程式時,常常會將一些參數存至機碼裡面,今天來簡單的筆記一下 Registry 的 CRUD。

在 64-bits 的作業系統下執行 32-bits 或 64-bits 應用程式時,預設寫入 Registry 會被作業系統寫入 Wow6432Node 的目錄底下。在 HKEY_LOCAL_MACHINE\SOFTWARE\ 底下寫入機碼,就會出現在 HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\,其目的是為了區分 32-bits 與 64-bits 作業系統的對應而產生的結果,只有真正的 64-bits 應用程式才能寫在 HKEY_LOCAL_MACHINE\SOFTWARE\ 目錄。

閱讀更多

       

[.NETCore][LexLibrary.Rbac] 基於 Role-based access control 實作驗證模組

LexLibrary.Rbac


本專案基於 Role-based access control 實作下列模組

  1. 登入 & 登出
  2. 註冊 & 驗證 Email
  3. 忘記密碼 & 重設密碼
  4. 角色模組
  5. 功能模組
  6. 驗證授權狀態 (可限制登入裝置數量)
  7. 基本資料維護

專案演示


閱讀更多

       

[C#][Line] 使用 Line Notify 開發訊息通知機器人 – 註冊篇

下一篇文章:[C#][Line] 使用 Line Notify 開發訊息通知機器人 – 開發篇

Line Notify 是 Line 提供的免費的服務,與網站服務連動完成後,LINE所提供的官方帳號「LINE Notify」將會傳送通知。
不僅可與多個服務連動,也可透過LINE群組接收通知。與 Line Messaging API 最大的差別在於他沒辦法在聊天室與使用者互動,只能單方面的傳送訊息給使用者。

閱讀更多