Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/csharp-4.0/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 在我最初的设计中,我是这样做的,但我不太确定如何实现它。另一方面,有些下载可能需要一段时间,是否有方法将进度报告回GUI线程。这是我喜欢连续执行DownloadDataASync()的原因之一,因为我可以订阅DownloadProgressChanged事_C#_C# 4.0_Thread Safety - Fatal编程技术网

C# 在我最初的设计中,我是这样做的,但我不太确定如何实现它。另一方面,有些下载可能需要一段时间,是否有方法将进度报告回GUI线程。这是我喜欢连续执行DownloadDataASync()的原因之一,因为我可以订阅DownloadProgressChanged事

C# 在我最初的设计中,我是这样做的,但我不太确定如何实现它。另一方面,有些下载可能需要一段时间,是否有方法将进度报告回GUI线程。这是我喜欢连续执行DownloadDataASync()的原因之一,因为我可以订阅DownloadProgressChanged事,c#,c#-4.0,thread-safety,C#,C# 4.0,Thread Safety,在我最初的设计中,我是这样做的,但我不太确定如何实现它。另一方面,有些下载可能需要一段时间,是否有方法将进度报告回GUI线程。这是我喜欢连续执行DownloadDataASync()的原因之一,因为我可以订阅DownloadProgressChanged事件。这不是一个关键的要求,只是很高兴知道这是否可能。谢谢你的解决方案。这并不是我在问题中所要求的,但答案让我重新思考设计,使之与线程安全无关。谢谢你的回答。我认为这个答案确实回答了我的问题,但我选择了sixlettervariables,因为他


在我最初的设计中,我是这样做的,但我不太确定如何实现它。另一方面,有些下载可能需要一段时间,是否有方法将进度报告回GUI线程。这是我喜欢连续执行
DownloadDataASync()
的原因之一,因为我可以订阅
DownloadProgressChanged
事件。这不是一个关键的要求,只是很高兴知道这是否可能。谢谢你的解决方案。这并不是我在问题中所要求的,但答案让我重新思考设计,使之与线程安全无关。谢谢你的回答。我认为这个答案确实回答了我的问题,但我选择了sixlettervariables,因为他的开箱即用解决方案帮助改进了我的设计,所以我几乎不必担心线程安全。我试着给你几张赞成票。
private WebClient webClient = new WebClient();
private Queue<Uri> requestQueue = new Queue<Uri>();

public Boolean DownloadNextASync()
{
    if (webClient.IsBusy)
        return false;

    if (requestQueue.Count == 0)
        return false

    var uri = requestQueue.Dequeue();

    webClient.DownloadDataASync(uri);

    return true;

}
var queue = new BlockingCollection<Uri>();
var maxClients = 4;

// Optionally provide another producer/consumer collection for the data
// var data = new BlockingCollection<Tuple<Uri,byte[]>>();

// Optionally implement CancellationTokenSource

var clients = from id in Enumerable.Range(0, maxClients)
              select Task.Factory.StartNew(
    () =>
    {
        var client = new WebClient();
        while (!queue.IsCompleted)
        {
            Uri uri;
            if (queue.TryTake(out uri))
            {
                byte[] datum = client.DownloadData(uri); // already "async"
                // Optionally pass datum along to the other collection
                // or work on it here
            }
            else Thread.SpinWait(100);
        }
    });

// Add URI's to search
// queue.Add(...);

// Notify our clients that we've added all the URI's
queue.CompleteAdding();

// Wait for all of our clients to finish
clients.WaitAll();
public static Task<byte[]> DownloadAsync(Uri uri, Action<double> progress)
{
    var source = new TaskCompletionSource<byte[]>();
    Task.Factory.StartNew(
        () =>
        {
            var client = new WebClient();
            client.DownloadProgressChanged
                += (sender, e) => progress(e.ProgressPercentage);
            client.DownloadDataCompleted
                += (sender, e) =>
                {
                    if (!e.Cancelled)
                    {
                        if (e.Error == null)
                        {
                            source.SetResult((byte[])e.Result);
                        }
                        else
                        {
                            source.SetException(e.Error);
                        }
                    }
                    else
                    {
                        source.SetCanceled();
                    }
               };
        });

    return source.Task;
}
// var urls = new List<Uri>(...);
// var progressBar = new ProgressBar();

Task.Factory.StartNew(
    () =>
    {
       foreach (var uri in urls)
       {
           var task = DownloadAsync(
               uri,
               p =>
                   progressBar.Invoke(
                       new MethodInvoker(
                       delegate { progressBar.Value = (int)(100 * p); }))
               );

           // Will Block!
           // data = task.Result;
       } 
    });
1. var valueToDequeue = this._internalList[this._startPointer];
2. this._startPointer = (this._startPointer + 1) % this._internalList.Count;
3. return valueToDequeue;
private readonly object _lock = new object();

...

lock (this._lock) { 
    // body of method
}