Blog chia sẽ kinh nghiệm lập trình và Technical VN. Nơi mà các bạn có thể học tập và tham khảo về những công nghệ mới nhất hiện nay về .NET
Chủ Nhật, 28 tháng 12, 2014
Đa số các chip xử lý (CPU) hiện còn đang hoạt động mà chúng ta biết đến đều có trên hai nhân(lõi) và tính năng ảo hóa - điều này làm cho các máy tính có được tốc độ xử lý nhanh hơn và khả năng đa nhiệm tốt hơn. Chính vì vậy để tận dụng hết khả năng của CPU chúng ta cần xử lý đồng thời trên nhiều lõi CPU cho nhiều bài toán khác nhau để tiết kiệm thời gian và nâng cao hiệu xuất. Trong vấn đề trên và trong lập trình ứng dụng .NET nói riêng chúng ta có thuật ngữ Thread (luồng xử lý/tiểu trình), chúng ta sẽ tìm hiểu về nó trong bài viết này.
Bạn không nên nhầm lẫn giữa process (tiến trình) và thread (tiểu trình). Process có thể hiểu là một instance của chương trình máy tính được thực thi, dựa trên hệ điều hành, hoàn toàn độc lập với các tiến trình khác. Còn thread là một nhóm lệnh được tạo ra để thực thi một tác vụ trong một process, chúng chia sẻ chung dữ liệu với nhau để xử lý, điều này là cần thiết nhưng cũng là nguyên nhân dễ gây ra lỗi nếu bạn không xử lý đúng cách. Các bạn có thể tham khảo về Class Thread tại đây
[caption id="" align="aligncenter" width="735"]
Trong nội dung này tôi không nói sâu về Thread trong C#, các bạn có thể tìm hiểm thêm tại đây, tôi sẽ xoay quanh về cách Thread hoạt động với các thành phần của WPF, xong tôi sẽ vẫn nhắc các bạn nhớ về Thread và Cách tạo một Thread như sau
[code language="csharp"]
public void CreateThread()
{
Thread thread = new Thread(new ThreadStart(MethodJob));
//MethodJob có thể là một delegate
//Run thread
thread.Start();
//Buộc hoãn thực thi đến khi được phép
thread.Suspend();
//Gọi thread tiếp tục chạy
thread.Resume();
//Buộc thread phải dừng
thread.Abort();
//Đợi thread xử lý xong
thread.Join();
}
private void MethodJob()
{
for (int i = 0; i < 100; i++)
{
//Do something
}
}
[/code]
Vấn đề Thread trong WPF - Truy cập an toàn một Control
Trong winform, một Thread phụ được tạo ra không thể tự mình truy cặp được các Control của Thread chính một cách an toàn được, chúng ta sẽ phải dùng delegate, trong WPF cũng thế; Nhưng trong WPF, mỗi Control đều chứa một đối tượng là Dispatcher - đối tượng này giúp đồng bộ các truy cập đến Control hiện tại và tránh sảy ra lỗi(tương tực việc lock(object)). Vì vậy, khi muốn thực hiện một truy cập an toàn đến một Control bất kỳ chúng ta cần gọi Dispatcher của control đó và phương thức xử lý Invoke(delegate), phương thức này chứa một delegate để làm việc với các thuộc tính của Control.
Ví dụ dưới đây phục vụ nhu cầu đếm lần lược từ 0->99 và hiện số đó lên TextBox
[code language="csharp"]
private void BtnRun_OnClick(object sender, RoutedEventArgs e)
{
//thread là một biến toàn cục kiểu Thread
if (thread != null)
{
thread.Abort(); //Dừng công viện hiện tại
}
//delegate được tạo theo định nghĩa Lambeda
thread = new Thread(new ThreadStart(() =>
{
//nội dung delegate
for (int i = 0; i < 100; i++)
{
Thread.Sleep(1000);
//An toàn truy cập với Dispatcher
txtData.Dispatcher.Invoke(() => txtData.Text = i.ToString());
//Vùng giới hạn an toàn rộng hơn
//this.Dispatcher.Invoke(() => txtData.Text = i.ToString());
}
}));
thread.IsBackground = true;
thread.Start();
}
[/code]
Ví dụ dưới đây phục vụ nhu cầu đếm lần lược từ x->99 và hiện số đó lên TextBox, với x là một số được truyền vào, tôi truyền vào số 10. Lưu ý tôi có hai delegate(Counter,Counters) chịu trách nhiệm hiển thị số đếm lên TextBox nhưng chúng có cách hiển thị khác nhau, các bạn hãy chú ý về cách truyền đối số cho Thread và hai delegate. Tôi gọi phương thức Invoke(delegate, object[]).
[code language="csharp"]
private void BtnRun2_OnClick(object sender, RoutedEventArgs e)
{
if (thread2 != null)
{
thread2.Abort();
}
thread2 = new Thread(new ParameterizedThreadStart(Run2));
thread2.IsBackground = true;
thread2.Start(10);
}
private delegate void Counter(int num);
private delegate void Counters(int num,int limit);
private void Run2(object numStart)
{
for (int i = (int)numStart; i < 100; i++)
{
//Cách truyền một tham số
this.Dispatcher.Invoke(new Counter(StartCount), i);
//Cách truyền nhiều tham số
this.Dispatcher.Invoke(new Counters(StartCounts), new object[] {i, 40});
Thread.Sleep(800);
}
}
private void StartCount(int num)
{
if (num < 20)
{
txtData2.Text = num.ToString();
}
else
{
txtData2.Text = "---";
}
}
private void StartCounts(int num,int limit)
{
if (num > 30 && num < limit)
{
txtData2.Text = num.ToString();
}
}
[/code]
Vấn đề Thread trong WPF - Show một Window từ Thread phụ
Nếu nhu cầu là một thread phụ được tạo ra để thực hiện một công việc nào đó và trong đó cần Show một Window thì bạn sẽ làm thế nào. Nếu bạn có thói quen dùng delegate như đoạn code bênh dưới chắc chắn rằng bạn sẽ gặp lỗi "The calling thread must be STA, because many UI components require this."
[code language="csharp"]
private void BtnRun4_OnClick(object sender, RoutedEventArgs e)
{
Thread thread5 = new Thread(new ThreadStart(ShowSubForm));
thread5.IsBackground = true;
thread5.Start();
}
private void ShowSubForm()
{
new MainWindow().Show();
}
[/code]
Vậy ta khắc phục lỗi trên như sau, cần tạo ra một Thread STA
[code language="csharp"]
private void BtnRun4_OnClick(object sender, RoutedEventArgs e)
{
Thread thread5 = new Thread(new ThreadStart(ShowSubForm));
thread5.SetApartmentState(ApartmentState.STA);
thread5.IsBackground = true;
thread5.Start();
}
private void ShowSubForm()
{
new MainWindow().Show();
//Nói rằng đây là một Window độc lập
System.Windows.Threading.Dispatcher.Run();
}
[/code]
Chúng ta còn cách khác đơn giản hơn với Dispathcher, bạn hảy thử
[code language="csharp"]
private void BtnRun4_OnClick(object sender, RoutedEventArgs e)
{
Thread thread5 = new Thread(new ThreadStart(ShowSubForm));
thread5.IsBackground = true;
thread5.Start();
}
private void ShowSubForm()
{
this.Dispatcher.Invoke(() =>
{
new MainWindow().Show();
});
}
[/code]
Vậy là chúng ta đã biết thêm về các vấn đề về Thread trong WPF, các bạn có thể tham khảo SourceCode
Chúc các bạn thành công!
Phạm Tuân
Search
Popular Posts
-
Phong cách thiết kế Material Design nhắm đến những đường nét đơn giản, sử dụng nhiều mảng màu đậm nổi bật, các đối tượng đồ họa trong giao ...
-
Hôm nay tôi sẽ giới thiệu với các bạn một Framework đến từ Microsoft - framework này không quá lớn nhưng là khá mạnh khi các bạn làm việc vớ...
-
WPF vượt trội hơn Winform về khoản Drawing , trong đó đặc biệt WPF hỗ trợ đồ họa rất tốt vì nó tương tác trực tiếp đến GPU. Hôm nay chúng t...
-
Hôm nay chúng ta sẽ tìm hiểu cách tạo ra các menu chuột phải trên ứng dụng WPF của mình. Ở bài này chúng ta xoay quanh việc tìm hiểu cách tạ...
-
Để dễ hiểu, các bạn hãy hình dung rằng: cùng một tập tin thực thi *.EXE nhưng bạn DoubleClick 10 lần cách quãng vào nó thì chuyện gì sẽ sảy ...
-
Trong bài viết trước tôi có giới thiệu về Extension Methods trong nguôn ngữ lập trình C#; hôm nay tôi sẽ nói về một vấn đề có ý nghĩa tương...
-
Hôm nay chúng ta sẽ thử đo xem thời gian query Data của "Foreach vs LinQ vs LinQasParallel" như thế nào. Tôi tạo một tool nhỏ để l...
-
Data Binding là kĩ thuật dùng để tạo gắn kết giữa phần giao diện ( UI ) và dữ liệu thông qua phần business logic hoặc giữa các đối tượng UI...
-
LOG4NET là một thư viện mã nguồn mở cho phép chúng ta tạo ra một hoặc nhiều tập tin log, kiểu log cũng như nội dung log một cách linh hoạt v...
-
Sau hai bài giới thiệu về Caliburn.Micro framework, hôm nay chúng ta sẽ cùng bắt tay vào làm một dự án nhỏ - HelloWorld. Step 1: Add referen...
Recent Posts
Blog Archive
-
▼
2014
(18)
-
▼
tháng 12
(18)
- WPF - Các Vấn Đề Về Multi-Thread Trong WPF (Đa Luồng)
- Modern UI For WPF Thiết Kế Giao diện Modern Win8 V...
- WPF - Thiết Kế Giao Diện METRO Win8 Với Thư Viện M...
- WPF - Validation ValidationRule và Vấn Đề Về Thông...
- WPF - Validation ValidationRule và Vấn Đề Về Thông...
- Parallel Class Trong C# và Vấn Đề Xử lý Song Song
- Tìm Hiểu Về Delegate Trong C# và Cách Truyền Dữ Li...
- Extension Methods - Thêm Một Phương Thức Ngoài Vào...
- Indexer trong C# - Kỹ Thuật Duyệt Qua Phần Tử Tron...
- SourceCode - DataBinding và ValueConverter
- WPF - DataBinding và chuyển đổi kiểu dữ liệu IValu...
- SourceCode - DataBinding và UpdateSourceTrigger
- WPF - DataBinding và cở chế tự động update dữ liệu
- SourceCode - DataBinding
- WPF – Cơ Bản về Data Binding
- WPF - Bộ Công Cụ Đắc Lực Cho Thiết Kế Expression S...
- WPF - Các Thành Phần Của WPF
- WPF - Tổng quan về Windows Presentation Foundation
-
▼
tháng 12
(18)
0 nhận xét:
Đăng nhận xét