Skip to content

Instantly share code, notes, and snippets.

@waynebaby
Last active August 29, 2015 13:56
Show Gist options
  • Save waynebaby/9276525 to your computer and use it in GitHub Desktop.
Save waynebaby/9276525 to your computer and use it in GitHub Desktop.
public class AsyncCompletion
{
static AsyncCompletion()
{
CompletedSource = new TaskCompletionSource<Unit>();
CompletedSource.SetResult(Unit.Default);
}
int completed = 0;
bool completionFetched ;
/// <summary>
/// 静态完成源
/// </summary>
static readonly TaskCompletionSource<Unit> CompletedSource;
/// <summary>
/// 跟着实例走的默认未完成源
/// </summary>
Lazy<TaskCompletionSource<Unit>> _incompletByDefaultSource =
new Lazy<TaskCompletionSource<Unit>>(() => new TaskCompletionSource<Unit>(), true);
public Task Completion
{
get
{
completionFetched = true;
//如果完成了就只返回静态完成源,否则返回引用中的默认未完成源
return (completed == 0) ? _incompletByDefaultSource.Value.Task : CompletedSource.Task;
}
}
public void Complete()
{
//标记完成
var isFirstComplete = Interlocked.Exchange(ref completed, 1) == 0;
//如果有人拿过默认未完成源 且当前是第一次完成 那么就把未完成源设置为完成]
if (completionFetched && isFirstComplete)
{
var cts = _incompletByDefaultSource.Value;
cts.SetResult(Unit.Default);
}
}
}
@waynebaby
Copy link
Author

··· csharp
public class AsyncCompletion
{
static AsyncCompletion()
{

        CompletedSource = new TaskCompletionSource<Unit>();
        CompletedSource.SetResult(Unit.Default);

    }

    public AsyncCompletion()
    {
        _incompletByDefaultSource = new Lazy<TaskCompletionSource<Unit>>(
                   () => (completed == 0) ? new TaskCompletionSource<Unit>() : CompletedSource,
                   true);

    }
    int completed = 0;


    /// <summary>
    /// 静态完成源
    /// </summary>

    static readonly TaskCompletionSource<Unit> CompletedSource;

    /// <summary>
    /// 跟着实例走的默认未完成源
    /// </summary>
    Lazy<TaskCompletionSource<Unit>> _incompletByDefaultSource;


    public Task Completion
    {
        get
        {
            //如果完成了就只返回静态完成源,否则返回引用中的默认未完成源
            return (completed == 0) ? _incompletByDefaultSource.Value.Task : CompletedSource.Task;
        }

    }

    public void Complete()
    {
        //标记完成

        var mark = Interlocked.Exchange(ref completed, 1);
        //如果有人拿过默认未完成源 且状态为未完 那么就把未完成源设置为完成(根据替换的值判断是否执行过)
        if (mark == 0) //没有执行过
        {
            if (_incompletByDefaultSource.IsValueCreated)
            {
                var cts = _incompletByDefaultSource.Value;
                if (!cts.Task.IsCompleted)
                {
                    cts.SetResult(Unit.Default);
                }
            }
        }

    }
}

···

原来的还是有问题 增加了double check

@waynebaby
Copy link
Author

    public class AsyncCompletion
    {
        static AsyncCompletion()
        {

            CompletedSource = new TaskCompletionSource<Unit>();
            CompletedSource.SetResult(Unit.Default);

        }

        public AsyncCompletion()
        {
            _incompletByDefaultSource = new Lazy<TaskCompletionSource<Unit>>(
                       () => (completed == 0) ? new TaskCompletionSource<Unit>() : CompletedSource,
                       true);

        }
        int completed = 0;


        /// <summary>
        /// 静态完成源
        /// </summary>

        static readonly TaskCompletionSource<Unit> CompletedSource;

        /// <summary>
        /// 跟着实例走的默认未完成源
        /// </summary>
        Lazy<TaskCompletionSource<Unit>> _incompletByDefaultSource;


        public Task Completion
        {
            get
            {
                //如果完成了就只返回静态完成源,否则返回引用中的默认未完成源
                return (completed == 0) ? _incompletByDefaultSource.Value.Task : CompletedSource.Task;
            }

        }

        public void Complete()
        {
            //标记完成

            var mark = Interlocked.Exchange(ref completed, 1);
            //如果有人拿过默认未完成源 且状态为未完 那么就把未完成源设置为完成(根据替换的值判断是否执行过)
            if (mark == 0) //没有执行过
            {
                if (_incompletByDefaultSource.IsValueCreated)
                {
                    var cts = _incompletByDefaultSource.Value;
                    if (!cts.Task.IsCompleted)
                    {
                        cts.SetResult(Unit.Default);
                    }
                }
            }

        }
    }

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment