[ThreadStatic]
ถูกกำหนดโดยใช้แอตทริบิวต์ในขณะที่ThreadLocal<T>
ใช้ทั่วไป เหตุใดจึงเลือกโซลูชันการออกแบบที่แตกต่างกัน ข้อดีและข้อเสียของการใช้ทั่วไปกับแอตทริบิวต์ในกรณีนี้คืออะไร?
[ThreadStatic]
ถูกกำหนดโดยใช้แอตทริบิวต์ในขณะที่ThreadLocal<T>
ใช้ทั่วไป เหตุใดจึงเลือกโซลูชันการออกแบบที่แตกต่างกัน ข้อดีและข้อเสียของการใช้ทั่วไปกับแอตทริบิวต์ในกรณีนี้คืออะไร?
คำตอบ:
สิ่งที่โพสต์ในบล็อกระบุไว้ในความคิดเห็นไม่ได้ทำให้ชัดเจน แต่ฉันพบว่ามีความสำคัญมากคือ[ThreadStatic]
ไม่ได้เริ่มต้นสิ่งต่างๆสำหรับทุกเธรดโดยอัตโนมัติ ตัวอย่างเช่นสมมติว่าคุณมีสิ่งนี้:
[ThreadStatic]
private static int Foo = 42;
หัวข้อแรกที่ใช้นี้จะเห็นเริ่มต้นได้ที่Foo
42
แต่เธรดที่ตามมาจะไม่ โปรแกรมเริ่มต้นใช้งานได้กับเธรดแรกเท่านั้น ดังนั้นคุณต้องเขียนโค้ดเพื่อตรวจสอบว่ามีการเริ่มต้นหรือไม่
ThreadLocal<T>
แก้ปัญหานั้นโดยให้คุณจัดหาฟังก์ชันการเริ่มต้น (ตามที่บล็อกของ Reed แสดง) ซึ่งทำงานก่อนครั้งแรกที่เข้าถึงรายการ
ในความคิดของฉันไม่เป็นประโยชน์อะไรกับการใช้แทน[ThreadStatic]
ThreadLocal<T>
ThreadLocal<T>
มีให้บริการใน .NET 4 ขึ้นไปและแอตทริบิวต์ยังมีอยู่ใน 3.5 และด้านล่าง ThreadStatic
ThreadLocal<T>
การใช้งานนั้นIDisposable
และมักจะบังคับให้คุณนำไปใช้IDisposable
ด้วยซึ่งบังคับให้ผู้โทรของคุณกำจัดคุณดังนั้นจึงนำไปใช้IDisposable
เช่นกัน ...
ThreadLocal
หรือThreadStatic
กับเธรดพูล ค่าเหล่านี้จะยังคงอยู่ตลอดอายุของพูลเธรดไม่ใช่เฉพาะสำหรับงานที่คุณกำหนดเท่านั้น นั่นอาจทำให้คุณมีปัญหาในบางวิธีที่ไม่ชัดเจน ดูstackoverflow.com/questions/561518/…และคำถามที่คล้ายกันสำหรับข้อมูลเพิ่มเติม
static
หรือไม่? ดูmsdn.microsoft.com/en-us/library/…
ThreadStatic Initialize บนเธรดแรกเท่านั้น ThreadLocal Initialize สำหรับแต่ละเธรด ด้านล่างนี้เป็นการสาธิตง่ายๆ:
public static ThreadLocal<int> _threadlocal =
new ThreadLocal<int>(() =>
{
return Thread.CurrentThread.ManagedThreadId;
});
public static void Main()
{
new Thread(() =>
{
for (int x = 0; x < _threadlocal.Value; x++)
{
Console.WriteLine("First Thread: {0}", x);
}
}).Start();
new Thread(() =>
{
for (int x = 0; x < _threadlocal.Value; x++)
{
Console.WriteLine("Second Thread: {0}", x);
}
}).Start();
Console.ReadKey();
}
ความคิดหลักที่อยู่เบื้องหลัง ThreadStatic คือการรักษาระดับแยกสำเนาของตัวแปรสำหรับแต่ละหัวข้อ
class Program
{
[ThreadStatic]
static int value = 10;
static void Main(string[] args)
{
value = 25;
Task t1 = Task.Run(() =>
{
value++;
Console.WriteLine("T1: " + value);
});
Task t2 = Task.Run(() =>
{
value++;
Console.WriteLine("T2: " + value);
});
Task t3 = Task.Run(() =>
{
value++;
Console.WriteLine("T3: " + value);
});
Console.WriteLine("Main Thread : " + value);
Task.WaitAll(t1, t2, t3);
Console.ReadKey();
}
}
ในตัวอย่างข้อมูลด้านบนเรามีสำเนาแยกต่างหากvalue
สำหรับแต่ละเธรดรวมถึงเธรดหลักด้วย
ดังนั้นตัวแปร ThreadStatic จะเริ่มต้นเป็นค่าเริ่มต้นในเธรดอื่นยกเว้นเธรดที่สร้างขึ้น
หากเราต้องการเริ่มต้นตัวแปรในแต่ละเธรดด้วยวิธีของเราเองให้ใช้ ThreadLocal