DownloadDataAsync + مندوب C # يعمل في main ولكن ليس في وظيفة من الدرجة

StackOverflow https://stackoverflow.com/questions/1653108

  •  22-07-2019
  •  | 
  •  

سؤال

وركضت هذا الرمز الأشخاص. عملت كرئيسي ولكن عندما وضعه في صفي كان لا يعمل. لماذا ا؟ كيفية استخدام WebClient.DownloadDataAsync ( ) طريقة في هذا السياق؟

ووتحطم البيانات قبل الميلاد == لاغيا وباطلا يطرح استثناء: (

.
public class Test2
    {
        public void func()
        {
            byte[] data = null;
            WebClient client = new WebClient();
            client.DownloadDataCompleted +=
                delegate(object sender, DownloadDataCompletedEventArgs e)
                {
                    data = e.Result;
                };
            Console.WriteLine("starting...");
            client.DownloadDataAsync(new Uri("https://stackoverflow.com/questions/"));
            while (client.IsBusy)
            {
                Console.WriteLine("\twaiting...");
                Thread.Sleep(100);
            }
            Console.WriteLine("done. {0} bytes received;", data.Length);
        }
    }

//i tried calling on form_load and a button click
new Test2().func();
هل كانت مفيدة؟

المحلول

وهذا الرمز لديه على حقل البيانات. ودعا مندوب مجهول DownloadDataCompleted من موضوع مختلف عن إجراء استدعاء data.Length وعند نقطة التي يتم استدعاء DownloadDataCompleted وIsBusy يصبح كاذبة. انه سباق بين المواضيع اثنين على الذين يصلون إلى البيانات أولا. إذا استدعت موضوع الرئيسي data.Length قبل أن يتم تحديد البيانات على موضوع حمل تحصل استثناء مرجع فارغة الخاص بك. فمن السهل أن نرى لا بد منه إذا كنت إجبار DownloadDataCompleted حذف فضفاضة دائما السباق أضاف Thread.Sleep () الدعوة إليها قبل أن يحدد البيانات.

وسوف الدول والترابط تبدو هذه:

Main Thread             Download Thread     client.IsBusy
Waiting....             downloading...      true
leaves waiting loop     calls delegate      false
calls data.Length       data = e.Result

وليس هناك طريقة لمعرفة أي موضوع سيتم تشغيل السطر الأخير أولا. على جهاز معالج متعددة، سواء تلك يمكن أن تعمل في وقت واحد.

وبما أن هذا هو أساس كل شيء على توقيت أحيانا أنه سوف يعمل وبعض الأحيان ستفشل. كنت بحاجة الى بعض نوع من التزامن (قفل) على جميع البيانات التي يتم الوصول إليها عن المواضيع موتليبلي.

نصائح أخرى

ونظرا لنموذج خيوط من winform (كما أشار shf301 الخروج)، لقد تعديل القوانين التي تعمل بالنسبة لي.

private void button1_Click(object sender, EventArgs e)
{
    func();
}
void func()
{
    WebClient client = new WebClient();
    byte[] data = null;
    long rcv = 0; //last number of bytes received

    //check data received for progress
    client.DownloadProgressChanged += delegate(object sender, DownloadProgressChangedEventArgs e)
    {
        if (e.BytesReceived - rcv > 1000)
        {
            Console.WriteLine("\tBytes Received: " + e.BytesReceived.ToString());
            rcv = e.BytesReceived;
        }
        //else don't report
        Thread.Sleep(1);
    };
    client.DownloadDataCompleted +=
        delegate(object sender, DownloadDataCompletedEventArgs e)
        {
            data = e.Result;
            Console.WriteLine("done. {0} bytes received;", data.Length);
        };
    Console.WriteLine("starting...");

    //fire and forget
    client.DownloadDataAsync(new Uri("http://stackoverflow.com/questions/"));
}

وهناك إخراج:

starting...
    Bytes Received: 8192
    Bytes Received: 11944
    Bytes Received: 15696
    Bytes Received: 20136
    Bytes Received: 24232
    Bytes Received: 28040
    Bytes Received: 32424
    Bytes Received: 36176
    Bytes Received: 40616
    Bytes Received: 44712
    Bytes Received: 48269
done. 48269 bytes received;

وكان يعمل للي؟

C:\TEMP\ConsoleApplication5\bin\Debug>ConsoleApplication5.exe
starting...
    waiting...
    waiting...
    waiting...
    waiting...
    waiting...
    waiting...
    waiting...
    waiting...
    waiting...
    waiting...
    waiting...
    waiting...
    waiting...
    waiting...
    waiting...
    waiting...
    waiting...
    waiting...
    waiting...
    waiting...
    waiting...
    waiting...
    waiting...
    waiting...
    waiting...
    waiting...
done. 48178 bytes received;

ما هي الفائدة من استخدام الأسلوب المتزامن إذا كنت انتظر النتيجة في الحلقة؟ مجرد استخدام النسخة متزامن:

public class Test2
    {
        public void func()
        {
            WebClient client = new WebClient();
            byte[] data = client.DownloadData(new Uri("http://stackoverflow.com/questions/"));
            Console.WriteLine("done. {0} bytes received;", data.Length);
        }
    }

//i tried calling on form_load and a button click
new Test2().func();
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top