async & คอย - สำรวจทางเลือก [ปิด]


15

ตอนนี้เรารู้ว่าสิ่งที่อยู่ในร้านสำหรับ C # 5 มีเห็นได้ชัดว่ายังคงเปิดสำหรับเราที่จะมีอิทธิพลต่อทางเลือกของสองคำใหม่สำหรับสasynchrony 'ที่ได้รับการประกาศโดย Anders Heijsberg เมื่อวานนี้ที่PDC10

async void ArchiveDocuments(List<Url> urls) {
    Task archive = null;
    for(int i = 0; i < urls.Count; ++i) {
        var document = await FetchAsync(urls[i]);
        if (archive != null)
            await archive;
        archive = ArchiveAsync(document);
    }
}

Eric Lippertมีคำอธิบายเกี่ยวกับการเลือกคำหลักสองคำในปัจจุบันและวิธีการที่พวกเขาเข้าใจผิดในการศึกษาการใช้งาน ความคิดเห็นมีข้อเสนออื่น ๆ

กรุณา - หนึ่งข้อเสนอแนะต่อคำตอบที่ซ้ำกันจะได้รับการอบ


โดยวิธีการที่ "ภาษาการเขียนโปรแกรมแบบบูรณาการไม่ตรงกัน" จะช่วยให้เราเลียบไม่ได้ค่อนข้างม้วนปิดลิ้นเช่นเดียวกับ LINQ;)
Benjol

1
เว้นแต่การก้าวกระโดดที่เด่นชัด
Conrad Frix

3
แต่ตัวย่อ "Runtime แบบบูรณาการภาษาแบบบูรณาการ" ขึ้นอย่างสวยงาม
glenatron

สิ่งนี้จะต้องไม่เป็นหัวข้อ
DeadMG

คำตอบ:


6

เนื่องจากฉันไม่ชัดเจนเกี่ยวกับความหมาย / ความจำเป็นasyncฉันไม่สามารถโต้เถียงกับมันได้จริง ๆ แต่ข้อเสนอแนะที่ดีที่สุดสำหรับการเปลี่ยนawaitคือ:

yield while (ดู! ไม่มีคำหลักใหม่)

โปรดทราบเมื่อคิดเกี่ยวกับเรื่องนี้อีกเล็กน้อยฉันสงสัยว่าการนำกลับมาใช้ใหม่whileในลักษณะนี้เป็นความคิดที่ดีหรือไม่ - แนวโน้มตามธรรมชาติคือการคาดหวังบูลีนในภายหลัง

(คิดว่า: การค้นหาคำหลักที่ดีเป็นเหมือนการค้นหาชื่อโดเมนที่ดี :)


+1 และโดยวิธีการที่คุณเอาชนะฉันเพื่อแสดงความคิดเห็นในบล็อกของเขาโดย 7 นาที ...
หมายเหตุถึงตัวเอง - คิดชื่อ

แต่คุณไม่จำเป็นต้องยอมให้มีการดำเนินการหากงานนั้นเสร็จสิ้นแล้ว แต่คุณมักจะรอคอยความสำเร็จของงาน (แม้ว่าจะไม่รอ)
Allon Guralnek

@ Allon คุณไม่จำเป็นต้องเรียกใช้ลูปเนื้อหาของwhile(x) {...}ทั้งสองหากxเป็นเท็จ
หมายเหตุตนเอง - คิดชื่อ

@ หมายเหตุ: ไม่มีกริยาในwhileค่ะ หากคุณเพิ่มกริยาเช่นdoนั้นคุณจะได้รับdo {...} while (x)ซึ่งจะดำเนินการร่างกายโดยไม่คำนึงถึง x (อย่างน้อยหนึ่งครั้ง) ข้อเสนอแนะของคุณyield whileดูเหมือนจะคล้ายกันมากdo whileแต่มีการรับรองคำกริยาที่ตรงกันข้ามซึ่งอาจทำให้เข้าใจผิดเล็กน้อย (แต่ไม่ใช่เรื่องใหญ่มาก) สิ่งที่ฉันไม่ชอบมากที่สุดyieldคือมันหมายถึงการนำกลไกไปใช้ จุดรวมของasync/ awaitคือให้คุณเขียนการดำเนินการแบบอะซิงโครนัสในสไตล์ซิงโครนัส yieldแบ่งสไตล์ซิงโครนัส
Allon Guralnek

คำหลักใหม่จำเป็นต้องเป็นสิ่งที่ไม่ดีใช่หรือไม่ ตามที่ฉันเข้าใจแล้วawaitคำหลักจะถูกรับรู้โดยบริบทดังนั้นคุณยังสามารถมีวิธีการหรือตัวแปรที่ชื่อว่า "คอย" ถ้าคุณต้องการ ในระดับหนึ่งฉันคิดว่าการใช้คำหลักใหม่สำหรับฟังก์ชั่นใหม่นั้นมีความสับสนน้อยกว่าการใช้คำหลักที่มีอยู่แล้วซ้ำเพื่อให้มีความหมายมากกว่าหนึ่งอย่าง (ตัวอย่างที่พูดเกินจริง: dangermouse.net/esoteric/ook.html )
Tim Goodman

5

ถ้าไม่มีคำหลักล่ะ?

ฉันต้องการให้คอมไพเลอร์ตระหนักว่าส่วนใหญ่เวลาที่ฉันเรียกใช้วิธีการแบบอะซิงโครนัสฉันต้องการผลลัพธ์ของมัน

Document doc = DownloadDocumentAsync();

แค่นั้นแหละ. สาเหตุที่ผู้คนกำลังคิดหนักใจกับคำหลักสำหรับสิ่งนี้เพราะมันเหมือนมีคำหลักสำหรับ "ทำสิ่งที่คุณทำถ้าสิ่งต่าง ๆ เป็นปกติอย่างสมบูรณ์" นั่นควรเป็นค่าเริ่มต้นไม่จำเป็นต้องมีคำหลัก

ปรับปรุง

ฉันแนะนำว่าคอมไพเลอร์ควรฉลาดด้วยการอนุมานประเภทเพื่อหาว่าจะทำอย่างไร เมื่อพิจารณาเพิ่มเติมเกี่ยวกับเรื่องนี้ฉันจะทำให้การใช้งานที่มีอยู่ใน CTP เป็นเช่นเดิม แต่ทำการเพิ่มเล็กน้อยเข้าไปอีกเล็กน้อยเพื่อลดกรณีที่คุณจำเป็นต้องใช้awaitคำหลักอย่างชัดเจน

[AutoAwait]เราคิดค้นแอตทริบิวต์: สิ่งนี้สามารถใช้ได้กับวิธีการเท่านั้น asyncวิธีหนึ่งที่จะได้รับนี้นำไปใช้กับวิธีการของคุณคือการทำเครื่องหมาย แต่คุณสามารถทำได้ด้วยมือเช่น:

[AutoAwait]
public Task<Document> DownloadDocumentAsync()

จากนั้นภายในasyncวิธีการใด ๆคอมไพเลอร์จะถือว่าคุณต้องการรอการโทรถึงDownloadDocumentAsyncดังนั้นคุณไม่จำเป็นต้องระบุ การเรียกใช้วิธีการนั้นจะรอโดยอัตโนมัติ

Document doc = DownloadDocumentAsync();

ตอนนี้ถ้าคุณต้องการ "รับความฉลาด" และรับสิ่งTask<Document>นั้นคุณต้องใช้โอเปอเรเตอร์startซึ่งสามารถปรากฏได้ก่อนการเรียกใช้เมธอด:

Task<Document> task = start DownloadDocumentAsync();

ฉันคิดว่าเรียบร้อย ตอนนี้การเรียกใช้เมธอดธรรมดาหมายถึงความหมาย: รอวิธีการให้เสร็จสมบูรณ์ และstartบ่งบอกถึงสิ่งที่แตกต่าง: ไม่ต้องรอ

สำหรับรหัสที่ปรากฏอยู่นอกasyncเมธอดวิธีเดียวที่คุณได้รับอนุญาตให้เรียกใช้[AutoAwait]เมธอดคือโดยนำหน้าด้วยstartวิธีนั้น นี่เป็นการบังคับให้คุณเขียนโค้ดที่มีความหมายเหมือนกันไม่ว่าจะปรากฏในasyncวิธีการหรือไม่ก็ตาม

จากนั้นฉันก็เริ่มที่จะโลภ! :)

ประการแรกฉันต้องการasyncนำไปใช้กับวิธีการเชื่อมต่อ:

interface IThing
{
    async int GetCount();
} 

โดยทั่วไปหมายความว่าวิธีการใช้งานจะต้องส่งคืนTask<int>หรือสิ่งที่เข้ากันได้กับawaitและผู้โทรไปที่วิธีการจะได้รับ[AutoAwait]พฤติกรรม

นอกจากนี้เมื่อฉันใช้วิธีการข้างต้นฉันต้องการที่จะสามารถเขียน:

async int GetCount()

ดังนั้นฉันไม่ต้องพูดถึงTask<int>ว่าเป็นประเภทส่งคืน

นอกจากนี้ฉันต้องการasyncนำไปใช้กับประเภทผู้ได้รับมอบหมาย (ซึ่งหลังจากทั้งหมดเป็นเหมือนอินเทอร์เฟซที่มีวิธีการเดียว) ดังนั้น:

public async delegate TResult AsyncFunc<TResult>();

asyncผู้ร่วมประชุมมี - คุณ guessed มัน - [AutoAwait]พฤติกรรม จากasyncวิธีการที่คุณสามารถเรียกมันและมันจะถูกawaited โดยอัตโนมัติ(เว้นแต่คุณเลือกที่จะเพียงแค่start) ดังนั้นถ้าคุณพูดว่า:

AsyncFunc<Document> getDoc = DownloadDocumentAsync;

นั่นเป็นเพียงการทำงาน มันไม่ใช่วิธีการโทร ยังไม่มีการเริ่มงานเลย - async delegateไม่ใช่งาน มันเป็นโรงงานสำหรับทำภารกิจ คุณสามารถพูดได้:

Document doc = getDoc();

และนั่นจะเริ่มงานและรอให้งานเสร็จและให้ผลลัพธ์แก่คุณ หรือคุณสามารถพูดว่า:

Task<Document> t = start getDoc();

ดังนั้นสถานที่แห่งหนึ่งในที่ซึ่ง "ประปา" รั่วไหลออกมาก็คือถ้าคุณต้องการสร้างผู้ร่วมงานให้กับasyncวิธีการคุณต้องรู้ว่าจะใช้async delegateประเภทใด ดังนั้นFuncคุณต้องพูดAsyncFuncแทนและอื่น ๆ แม้ว่าสักวันหนึ่งสิ่งนั้นอาจได้รับการแก้ไขโดยการอนุมานประเภทที่ปรับปรุงแล้ว

คำถามอื่นคือสิ่งที่จะเกิดขึ้นถ้าคุณบอกว่าเริ่มต้นด้วยวิธีธรรมดา (ไม่ async) เห็นได้ชัดว่าข้อผิดพลาดในการรวบรวมจะเป็นตัวเลือกที่ปลอดภัย แต่มีความเป็นไปได้อื่น ๆ


นี่อาจเป็นไปได้ด้วยการแปลงโดยนัย แต่อย่างอื่นจะต้องมีการประเมินผลจากซ้ายไปขวาของคำสั่ง ฉันคิดว่าฉันยังคงขัดกับสิ่งนี้เพราะมันป้องกันการใช้งานvarอาจจะต้องใช้ชื่อประเภทที่ชัดเจนมานานและยังคลุมเครือระหว่างawaitเคสกับเคสที่มีคนเรียกบังเอิญวิธี async แทนวิธีซิงโครนัสปกติ ดูเหมือนง่ายในตอนแรก แต่จริงๆแล้วเป็นการละเมิดหลักการของความประหลาดใจน้อยที่สุด
Aaronaught

@Aaraught - ทำไมมันป้องกันการใช้งานvarหรือไม่ ฉันสงสัยว่าคุณกำลังตอบกลับการแก้ไขคำตอบก่อนหน้าของฉันหรือไม่ ... ฉันเขียนใหม่ทั้งหมด ตอนนี้คุณสามารถนึกถึงข้อเสนอแนะดังต่อไปนี้: หากวิธีการถูกทำเครื่องหมายด้วยคุณสมบัติพิเศษมันเป็นราวกับว่าawaitคำหลักจะถูกแทรกโดยอัตโนมัติในด้านหน้าของการโทรไปที่วิธีการนั้น (เว้นแต่คุณจะระงับสิ่งนี้ด้วยstartคำนำหน้า) ทุกอย่างยังคงเหมือนเดิมใน CTP และvarทำงานได้ดี
Daniel Earwicker

จริง ๆ แล้วฉัน ... แปลกที่ฉันตัดสินใจที่จะทบทวนหัวข้อนี้และตอบกลับคำตอบของคุณในเวลาเดียวกันกับที่คุณตัดสินใจที่จะแก้ไข ฉันจะอ่านใหม่ตอนนี้ ...
Aaronaught

1
ฉันชอบการผันกลับของคำหลักที่รอคอย public async Task<int> FooAsync()และฉันยังไม่ชอบสามซ้ำซ้อนของ
Allon Guralnek

1
ใช่ฉันเห็นว่าการตั้งชื่อแบบ Async-postfix เป็นสัญญาณว่าบางสิ่งอาจถูกจับอย่างเป็นทางการมากขึ้น โดยทั่วไปหากมีกฎว่า "วิธีการเช่นนี้ควรตั้งชื่อเป็นวิธีที่แน่นอนเพื่อให้ผู้คนรู้วิธีเรียกพวกเขาอย่างถูกต้อง" จากนั้นตามกฎเดียวกันสามารถใช้เพื่อระบุวิธีการเหล่านั้นด้วยวิธีที่แน่นอนและจากนั้นคอมไพเลอร์ ช่วยคุณโทรหาพวกเขาอย่างถูกต้อง
Daniel Earwicker

4
hearken unto AsyncFetch(…)

(ถ้าคุณไม่เข้าใจลองอ่านบล็อกของ Eric อย่างน้อยก็ดีกว่าfor sooth Romeo wherefore art thou AsyncFetch(…))


(ผู้ที่ไม่มีอารมณ์ขันไม่จำเป็นต้องใช้)
หมายเหตุสำหรับตนเอง - คิดชื่อ

4

ฉันคิดว่าใช้ได้asyncแต่อาจเป็นเพราะฉันเชื่อมโยงกับเพจ async ASP.NET - แนวคิดเดียวกัน

สำหรับawaitคำหลักที่ฉันชอบหรือcontinue afterresume after

ฉันไม่ชอบyieldหรือรูปแบบใด ๆ ของมันเพราะความหมายเป็นเช่นนั้นวิธีการที่อาจไม่เคยให้การดำเนินการจริง; มันขึ้นอยู่กับสถานะของงาน


ผมชอบสำหรับresume after awaitบางทีอาจจะเรียกว่าasync resumable
ทิมกู๊ดแมน

ถึงแม้ว่าผมจะต้องการเพียงafterที่continue afterวิธีการที่มีข้อได้เปรียบการดำเนินงานที่แข็งแกร่ง: มันมีคำหลักตามบริบทที่มีอยู่ในขณะนี้ แต่มีไวยากรณ์ที่ไม่เข้ากันได้กับการใช้งานในปัจจุบัน ที่รับประกันได้ว่าการเพิ่มจะไม่ทำลายรหัสที่มีอยู่ เมื่อใช้คำหลักใหม่ทั้งหมดการใช้งานจะต้องรับมือกับการใช้คำที่เป็นไปได้ในฐานะตัวบ่งชี้ของโค้ดที่เก่ากว่าซึ่งอาจจะค่อนข้างยุ่งยาก
Edurne Pascual

3

ฉันเพิ่มความคิดเห็นในบล็อกของ Eric ด้วยฉันไม่เห็นปัญหาใด ๆ เกี่ยวกับการใช้คำหลักเดียวกัน async

var data = async DownloadFileAsync(url);

ฉันแค่แสดงว่าฉันต้องการดาวน์โหลดไฟล์แบบอะซิงโครนัส มีความซ้ำซ้อนเล็กน้อยที่นี่ "async" ปรากฏขึ้นสองครั้งเพราะอยู่ในชื่อเมธอดด้วย คอมไพเลอร์อาจจะฉลาดเป็นพิเศษและตรวจจับการประชุมว่าวิธีที่ลงท้ายด้วย "Async" เป็นวิธีการ async แบบ infact และเพิ่มสิ่งนั้นให้เราในโค้ดที่คอมไพล์แล้ว ดังนั้นคุณอาจต้องการโทรแทน

var data = async DownloadFile(url);

ตรงข้ามกับการเรียกแบบซิงโครนัส

var data = DownloadFile(url);

เฮ้เราก็ควรจะสามารถกำหนดพวกเขาในลักษณะเดียวกันเนื่องจากคำหลัก async มีอยู่ในการประกาศของเราทำไมเราต้องเพิ่ม "Async" ในแต่ละชื่อวิธีด้วยตนเอง - คอมไพเลอร์สามารถทำเพื่อเรา


ฉันชอบน้ำตาลที่คุณเพิ่มถึงแม้ว่าผู้ชาย C # อาจจะไม่ทำก็ตาม (FWIW พวกเขาทำสิ่งที่คล้ายกันแล้วเมื่อค้นหาชื่อแอตทริบิวต์)
หมายเหตุตนเอง - คิดชื่อ

2
และเนื่องจากasyncคำหลักในวิธีการนั้นเป็นเพียงความดี (ถ้าฉันเข้าใจถูกต้อง) ฉันสงสัยว่าสิ่งที่ดีที่สุดจะไม่ทำตรงข้ามกับสิ่งที่คุณแนะนำ: ทิ้งasyncวิธีนั้นและใช้มัน awaitที่พวกเขากำลังมี
Benjol

นั่นเป็นความเป็นไปได้ คีย์เวิร์ด async ของ delcaration นั้นมีไว้เพื่อความสะอาดเท่านั้น ฉันต้องการเก็บไว้ที่นั่น แต่ไม่ต้องการให้เราเพิ่ม "Async" ในชื่อเมธอด เช่นasync Task<Byte[]> DownloadFile(...)แทนที่จะTask<Byte[]> DownloadFileAsync(...)(หลังจะเป็นลายเซ็นที่รวบรวมอยู่แล้ว) ทั้งสองวิธีใช้งานได้
Mark H

ฉันก็ไม่ได้เป็นแฟนของเรื่องนี้เหมือนกัน ในความคิดเห็นก่อนหน้าฉันต้องชี้ให้เห็นว่ารุ่นสุดท้ายของคุณละเมิดหลักการของความประหลาดใจอย่างน้อยที่สุดเนื่องจากมันเป็นการเรียกวิธีการที่แตกต่างอย่างสิ้นเชิงจากที่เขียนไว้และการใช้งานและลายเซ็นของวิธีการนั้นขึ้นอยู่กับชั้นเรียน . แม้แต่รุ่นแรกก็มีปัญหาเพราะมันไม่ได้พูดอะไรเลย (อะซิงโครนัสรันวิธีอะซิงโครนัสนี้ใช่ไหม) ความคิดที่เราพยายามแสดงออกคือการดำเนินการต่อเนื่องหรือรอการตัดบัญชีและนี่ไม่ได้แสดงถึงสิ่งนั้นเลย
Aaronaught

3

async = task - มันปรับเปลี่ยนฟังก์ชั่นเพื่อกลับงานดังนั้นทำไมไม่ใช้คำหลัก "งาน"?

await = finish - เราไม่จำเป็นต้องรอ แต่ภารกิจต้อง "เสร็จสิ้น" ก่อนที่จะใช้ผลลัพธ์


เป็นการยากที่จะโต้แย้งกับความเรียบง่ายที่นี่
sblom

2

yield untilผมชอบ yield whileแนะนำแล้วดีมากและไม่แนะนำคำหลักใหม่ใด ๆ แต่ฉันคิดว่า "จนกระทั่ง" จับภาพพฤติกรรมได้ดีขึ้นเล็กน้อย

ฉันคิดว่าyield <something>เป็นความคิดที่ดีเพราะผลตอบแทนแล้วจับความคิดในการทำให้ส่วนที่เหลือของวิธีการต่อเนื่องเป็นอย่างดี บางทีบางคนอาจนึกถึงคำที่ดีกว่า "จนถึง"


2

ฉันต้องการลงทะเบียนการโหวตของฉันสำหรับคำแนะนำของ Aaron G comefrom- การใช้งานที่เหมาะสมครั้งแรกที่ฉันได้เห็นคำสั่งCOMEFROMของINTERCAL แนวคิดก็คือมันเป็นสิ่งที่ตรงกันข้ามกับ GOTO (กระโดดออกไปจากคำสั่ง GOTO) ที่ทำให้บางสถานที่ในรหัสของคุณข้ามไปที่คำสั่ง COMEFROM


2

เนื่องจากเรากำลังติดต่อกับTask<T>s วิธีการใช้startเป็นคำสำคัญที่นำหน้าคำสั่งเช่นเดียวกับใน:

start var document = FetchAsync(urls[i]);


อืมบางทีอาจfinishจะดีกว่าstartใช่มั้ย
ตัวเอก

1

เป็นที่น่าสังเกตว่า F # ยังใช้asyncคำหลักในเวิร์กโฟลว์ของ async ซึ่งเป็นสิ่งที่ค่อนข้างแน่นอนเหมือนกับฟังก์ชั่น async ใหม่ใน C # 5 ดังนั้นฉันจะเก็บมันไว้เหมือนเดิม

สำหรับawaitคำหลักใน F # พวกเขาเพียงแค่ใช้แทนlet! letC # ไม่มีรูปแบบการมอบหมายเดียวกันดังนั้นพวกเขาต้องการบางสิ่งที่ด้านขวาของ=เครื่องหมาย ดังที่ Benjol กล่าวว่ามันทำหน้าที่เหมือนกันyieldดังนั้นมันควรจะเป็นความแตกต่างของสิ่งนั้น


1
"รอ" ไม่จำเป็นต้องอยู่ในการมอบหมายเลย (แม้ว่าโดยทั่วไปแล้วจะเป็น) มันเป็นเรื่องถูกกฎหมายในฐานะผู้ดำเนินการเกี่ยวกับการแสดงออกใด ๆ ที่มีประเภทที่เราสามารถหา GetAwaiter ได้ (กฎที่แน่นอนยังไม่สามารถใช้งานในรูปแบบที่เผยแพร่ได้)
Eric Lippert

1
@ Eric ใน F # ที่จะเป็นdo!แต่คุณรู้ว่า ...
Benjol

1

yield async FetchAsync(..)


สิ่งนี้จะเป็นไปอย่างสมบูรณ์แบบด้วยasyncตัวปรับแต่งที่คุณต้องใช้กับวิธีการที่คุณเรียกใช้ และความหมายของกระแสไฟฟ้าyield returnนั่นก็คือคุณส่งคืนและให้การประมวลผลแก่โค้ดที่แจกแจงในกรณีนี้คุณจะยอมให้การประมวลผลของคุณเป็นวิธีอะซิงโครนัส

ลองนึกภาพว่าในอนาคตจะมีการใช้งานอื่นyieldเราสามารถเพิ่มyield xตำแหน่งที่ x เป็นคุณลักษณะใหม่ที่เป็นประกายเงางามแทนที่จะมีคำหลักที่แตกต่างกันเหล่านี้ทั้งหมดสำหรับการทำสิ่งเดียวกันโดยส่วนใหญ่เป็นการดำเนินการที่ให้ผลตอบแทน

ตรงไปตรงมาฉันไม่เข้าใจข้อโต้แย้ง 'ไม่ยอมให้มีการประหารชีวิต' ท้ายที่สุดแล้วจุดที่เรียกวิธีอื่นนั้นไม่ได้เป็น 'การประมวลผลที่ได้รับ' สำหรับวิธีการนั้นหรือไม่ ไม่ว่าจะเป็นแบบอะซิงโครนัสหรือไม่? ฉันพลาดอะไรบางอย่างที่นี่?

และดีสำหรับคุณถ้าการasyncส่งคืนแบบซิงโครนัส แต่มีคำหลักควรมีความหมายว่ามีโอกาสที่วิธีนั้นจะทำงานแบบอะซิงโครนัสและคุณจะยอมให้มีการดำเนินการกับวิธีอื่น วิธีการของคุณควรคำนึงถึงสิ่งนั้นโดยไม่คำนึงว่าวิธีการโทรแบบอะซิงโครนัสจริงหรือไม่

IMO ฉันคิดว่ากรณีต่างๆที่ 'ไม่ยอม' เป็นรายละเอียดการปฏิบัติ ฉันต้องการรับรองความสอดคล้องในภาษา (เช่นการนำมาใช้ซ้ำyield)


0

วิธีการเกี่ยวกับcompleteในขณะที่ "ฉันต้องการให้งานเสร็จ"?

Task<byte[]> downloadTask = DownloadFileAsync(url);
byte[] data = complete downloadTask;

1
ทำไมต้องลงคะแนน? อย่างน้อยอธิบายด้วยตัวคุณเองหลังจาก downvoting
Allon Guralnek

0

task(สำหรับการประกาศเมธอด) และasync(ภายในเมธอดเนื้อหา)


คำตอบนี้ช้าไปหน่อยพวกเขาตัดสินเป็นasyncและรอหนึ่งปีที่ผ่านมา
เจ Elston
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.