E-posta istemcilerinde çoklu iş parçacığı desteği

ImapClient ve Pop3Client gibi mail istemcileri, kullanıcıların bunları çok iş parçacıklı ortamda kullanmasına izin verir. Mail istemcileri, bir sunucu ile bir veya daha fazla bağlantı kurabilir. İstemciler içinde bir bağlantı kümesini yönetmek için bağlantı havuzu (connection pool) kullanılır. Aynı anda oluşturulup kullanılabilecek bağlantı sayısı, CredentialsByHostClient.MaxConnectionsPerServer özelliği ile sınırlıdır. Bu özellik 1 ya da daha büyük bir değere ayarlanabilir. Varsayılan olarak bu özellik 10’dur. Bağlantı için komut kuyruğu, çok iş parçacıklı işlemleri desteklemek amacıyla uygulanmıştır. Komutlar, protokolda tanımlanan basit işlemleri (Noop, Authenticate vb.) içerir. Kullanıcı, mevcut bağlantı sayısından daha fazla komut çalıştırmaya başlayabilir. Ancak komutlar, istemci bir bağlantı oluşturabildiğinde yürütülür.

Çok iş parçacıklı ortamda mail istemcilerini kullanma yöntemleri

E-posta istemcileri aşağıdaki davranışa sahiptir:

1. MaxConnectionsPerServer = 1 olduğunda istemci 1 bağlantı oluşturur, kimlik doğrulama ve yetkilendirme yapar. Bu bağlantı, istemci vazgeçirilene kadar çalışır durumda tutulur. Farklı iş parçacıklarından gelen tüm işlemler, ana bağlantıda bulunan tek bir komut kuyruğuna yönlendirilir.

2. MaxConnectionsPerServer > 1 olduğunda istemci gerekli sayıda bağlantı oluşturur, her bağlantı için kimlik doğrulama ve yetkilendirme yapar. Bir bağlantı ana bağlantı olarak ayrılır. Bu bağlantı, istemci vazgeçirilene kadar çalışır durumda tutulur. Diğer tüm bağlantılar talep üzerine oluşturulur ve vazgeçirilir. Bu tür bağlantıların azami sayısı MaxConnectionsPerServer özelliğiyle tanımlanır; örneğin MaxConnectionsPerServer = 2 ise biri ana bağlantı olarak ayrılır, ikinci bağlantı diğer iş parçacıklarında yürütülen işlemler için ek bağlantı olarak kullanılır. Benzer şekilde MaxConnectionsPerServer = 3 ise ilk bağlantı ana bağlantı, iki diğer bağlantı ise ek olarak kullanılır. Yeni bir iş parçacığından bağlantı talebi geldiğinde ve tüm bağlantılar zaten kullanımda olduğunda, istemci kullanılabilir bağlantı sayısı azalıncaya kadar bekler. Bu, bağlantıların doğru şekilde vazgeçirilmesinin neden bu kadar önemli olduğunu açıklayan çok önemli bir noktadır.

Örnekler

Kullanıcı, farklı iş parçacıklarında çeşitli şekillerde işlemler yürütebilir. Bunlar iki tipe ayrılabilir:

1. Kullanıcı, istemcide tanımlı asenkron (Begin/End) metodları kullanır. Bu durumda e-posta istemcisi ihtiyaç duyulduğunda yeni iş parçacıkları başlatır. İstemcide görev kuyruğu uygulanmıştır (lütfen bağlantıdaki komut kuyruğu ile karıştırmayın). Görev, bağlantı mevcutsa yürütülebilir. Kullanılan bağlantı sayısı limit değerinden düşük olduğunda, istemci yeni bir bağlantı oluşturur, mevcut görev için bir iş parçacığı yaratır ve bu görevi yürütür. Asenkron operasyonların kullanımı örneği:

2. Kullanıcı, Thread, ThreadPool, Task veya bu amaçla tasarlanmış başka nesneler kullanarak iş parçacıkları oluşturabilir. Ayrıca üçüncü parti kodda oluşturulan iş parçacıkları da kullanılabilir. Bu süreçte istemcinin iki davranış modeli vardır

a. Kullanıcı, iş parçacığındaki işlemler için ek bağlantı oluşturmadıysa, bu iş parçacığının tüm işlemleri ana bağlantıya gönderilecek komut kuyruğuna yönlendirilir. Yeni bağlantı oluşturmadan ek bir iş parçacığında yapılan işlemlere bir örnek; tüm işlemler ana bağlantı üzerinden gerçekleştirilir:

b. Kullanıcı, ek bir iş parçacığı için yeni bir bağlantı oluşturma metodunu çalıştırdığında, bu iş parçacığı yeni bağlantılara izin verilene kadar kota değeri değişene kadar bloklanır. Ardından yeni bağlantı oluşturulur. Bu bağlantı, bu iş parçacığındaki tüm işlemler için varsayılan bağlantı olarak ayarlanır. İş parçacığındaki tüm işlemler tamamlandıktan sonra bağlantı vazgeçirilmelidir. Yeni bağlantılar oluşturmak için CredentialsByHostClient.CreateConnection metodunu kullanın. Bu yöntem, IDisposable arayüzünü uygulayan bir nesne döndürür. Bağlantıyı serbest bırakmak için Dispose metodu çağrılmalıdır. Bağlantının oluşturulması ve vazgeçirilmesi, e-posta işlemlerinin yürütüldüğü iş parçacığı içinde gerçekleştirilmelidir. Mail istemcisinin oluşturulduğu iş parçacığında yeni bir bağlantı oluşturma girişimi bir hataya yol açar, çünkü bu iş parçacığı o anda yeni bağlantı oluşturmak için kullanılamaz. Ayrıca MaxConnectionsPerServer = 1 iken yeni bağlantı oluşturulması mümkün değildir. Ek bir iş parçacığı için yeni bağlantı oluşturma kod örneği:

Öneriler

Kullanıcının tüm komutları ana bağlantıya gönderdiği durumda, farklı iş parçacıklarından gelen komutların karışması gibi bir durum ortaya çıkabilir. Kullanıcı, hangi komutların sıralarına bağlı olduğunu anlamalı ve bu komutların senkronizasyonu için önlemler almalıdır. Ayrıca komutların farklı oturumlarda (IMAP/POP3) çalıştırılması olasılığı da göz önünde bulundurulmalıdır. FetchMessage, AppendMessage ve Send gibi en zaman alıcı işlemler, muhtemelen yeni bir iş parçacığı ve yeni bir bağlantı ile gerçekleştirilmelidir. Ancak Delete gibi hızlı işlemler ana bağlantı ile yapılabilir. Lütfen yeni bağlantının başlatılmasının zaten zaman tüketen bir işlem olduğunu unutmayın.