Bagikan melalui


ServiceBehaviorAttribute.ConcurrencyMode Properti

Definisi

Mendapatkan atau mengatur apakah layanan mendukung satu utas, beberapa utas, atau panggilan masuk kembali.

public:
 property System::ServiceModel::ConcurrencyMode ConcurrencyMode { System::ServiceModel::ConcurrencyMode get(); void set(System::ServiceModel::ConcurrencyMode value); };
public System.ServiceModel.ConcurrencyMode ConcurrencyMode { get; set; }
member this.ConcurrencyMode : System.ServiceModel.ConcurrencyMode with get, set
Public Property ConcurrencyMode As ConcurrencyMode

Nilai Properti

Salah ConcurrencyMode satu nilai; defaultnya adalah Single.

Pengecualian

Nilai bukan salah ConcurrencyMode satu nilai.

Contoh

Contoh kode berikut menunjukkan perbedaan antara menggunakan Single, , Reentrantdan Multiple. Sampel ini tidak dikompilasi tanpa implementasi nyata di belakangnya, tetapi menunjukkan jenis utas menjamin bahwa Windows Communication Foundation (WCF) membuat dan apa artinya untuk kode operasi Anda.

using System;
using System.ServiceModel;

[ServiceContract]
public interface IHttpFetcher
{
  [OperationContract]
  string GetWebPage(string address);
}

// These classes have the invariant that:
//     this.slow.GetWebPage(this.cachedAddress) == this.cachedWebPage.
// When you read cached values you can assume they are valid. When
// you write the cached values, you must guarantee that they are valid.
// With ConcurrencyMode.Single, WCF does not call again into the object
// so long as the method is running. After the operation returns the object
// can be called again, so you must make sure state is consistent before
// returning.
[ServiceBehavior(ConcurrencyMode = ConcurrencyMode.Single)]
class SingleCachingHttpFetcher : IHttpFetcher
{
    string cachedWebPage;
    string cachedAddress;
    readonly IHttpFetcher slow;

    public string GetWebPage(string address)
    {
        // <-- Can assume cache is valid.
        if (this.cachedAddress == address)
        {
            return this.cachedWebPage;
        }

        // <-- Cache is no longer valid because we are changing
        // one of the values.
        this.cachedAddress = address;
        string webPage = slow.GetWebPage(address);
        this.cachedWebPage = webPage;
        // <-- Cache is valid again here.

        return this.cachedWebPage;
        // <-- Must guarantee that the cache is valid because we are returning.
    }
}

// With ConcurrencyMode.Reentrant, WCF makes sure that only one
// thread runs in your code at a time. However, when you call out on a
// channel, the operation can get called again on another thread. Therefore
// you must confirm that state is consistent both before channel calls and
// before you return.
[ServiceBehavior(ConcurrencyMode = ConcurrencyMode.Reentrant)]
class ReentrantCachingHttpFetcher : IHttpFetcher
{
  string cachedWebPage;
  string cachedAddress;
  readonly SlowHttpFetcher slow;

  public ReentrantCachingHttpFetcher()
  {
    this.slow = new SlowHttpFetcher();
  }

  public string GetWebPage(string address)
  {
    // <-- Can assume that cache is valid.
    if (this.cachedAddress == address)
    {
        return this.cachedWebPage;
    }

    // <-- Must guarantee that the cache is valid, because
    // the operation can be called again before we return.
    string webPage = slow.GetWebPage(address);
    // <-- Can assume cache is valid.

    // <-- Cache is no longer valid because we are changing
    // one of the values.
    this.cachedAddress = address;
    this.cachedWebPage = webPage;
    // <-- Cache is valid again here.

    return this.cachedWebPage;
    // <-- Must guarantee that cache is valid because we are returning.
  }
}

// With ConcurrencyMode.Multiple, threads can call an operation at any time.
// It is your responsibility to guard your state with locks. If
// you always guarantee you leave state consistent when you leave
// the lock, you can assume it is valid when you enter the lock.
[ServiceBehavior(ConcurrencyMode = ConcurrencyMode.Multiple)]
class MultipleCachingHttpFetcher : IHttpFetcher
{
  string cachedWebPage;
  string cachedAddress;
  readonly SlowHttpFetcher slow;
  readonly object ThisLock = new object();

  public MultipleCachingHttpFetcher()
  {
    this.slow = new SlowHttpFetcher();
  }

  public string GetWebPage(string address)
  {
    lock (this.ThisLock)
    {
      // <-- Can assume cache is valid.
      if (this.cachedAddress == address)
      {
          return this.cachedWebPage;
          // <-- Must guarantee that cache is valid because
          // the operation returns and releases the lock.
      }
      // <-- Must guarantee that cache is valid here because
      // the operation releases the lock.
    }

    string webPage = slow.GetWebPage(address);

    lock (this.ThisLock)
    {
      // <-- Can assume cache is valid.

      // <-- Cache is no longer valid because the operation
      // changes one of the values.
      this.cachedAddress = address;
      this.cachedWebPage = webPage;
      // <-- Cache is valid again here.

      // <-- Must guarantee that cache is valid because
      // the operation releases the lock.
    }

    return webPage;
  }
}

Keterangan

Properti ini menunjukkan apakah instans layanan dapat menangani satu utas atau beberapa utas yang dijalankan secara bersamaan, dan jika satu utas, apakah reentrancy didukung.

Nota

Properti ConcurrencyMode berinteraksi dengan beberapa pengaturan lain. Misalnya, jika InstanceContextMode nilai diatur ke Single hasilnya adalah layanan Anda hanya dapat memproses satu pesan pada satu waktu kecuali Anda juga mengatur nilai ke ConcurrencyModeMultiple. Properti ini juga menghasilkan perilaku dalam kombinasi dengan ServiceContractAttribute.SessionMode properti . Untuk detailnya, lihat Sesi, Instancing, dan Konkurensi.

Pengaturan ConcurrencyMode untuk Single menginstruksikan sistem untuk membatasi instans layanan ke satu utas eksekusi pada satu waktu, yang membebaskan Anda dari masalah utas. Nilai Multiple berarti bahwa objek layanan dapat dijalankan oleh beberapa utas kapan saja. Dalam hal ini, Anda harus memastikan keamanan utas.

Reentrant juga membatasi akses ke satu utas pada satu waktu; saat operasi sedang diproses, tidak ada pesan lain yang dapat memasuki operasi. Jika selama operasi panggilan ke layanan lain pergi, pesan saat ini kehilangan kunci pada operasi, yang bebas untuk memproses pesan lain. Ketika panggilan layanan kembali, kunci direestablish dan pesan asli dapat terus memproses ke kesimpulannya atau sampai panggilan lain keluar dari operasi terjadi.

Penting

Meskipun Single membatasi instans layanan ke satu utas eksekusi sekaligus, Anda juga harus mengatur MaxConcurrentCalls ke 1 untuk menjamin tidak ada pesan yang tidak berurutan.

Selain itu, Anda bertanggung jawab untuk membiarkan status objek Anda konsisten sebelum panggilan dan Anda harus mengonfirmasi bahwa data operasi-lokal valid setelah panggilan. Perhatikan bahwa instans layanan tidak terkunci hanya dengan memanggil layanan lain melalui saluran WCF. Dalam hal ini, layanan yang disebut dapat memasukkan kembali layanan pertama melalui panggilan balik. Jika layanan pertama tidak masuk kembali, urutan panggilan menghasilkan kebuntuan. Untuk detailnya, lihat ConcurrencyMode.

Selama panggilan keluar dari operasi pemrosesan, data yang tidak lokal ke operasi dapat dimodifikasi. (Data status lokal dijamin valid ketika pesan asli melanjutkan pemrosesan.) Akibatnya, sebelum panggilan keluar, Anda harus memastikan bahwa data non-lokal valid untuk panggilan masuk lainnya dan memvalidasi ulang data non-lokal setelah panggilan keluar kembali.

Kode pseudo berikut mengilustrasikan pola yang diperlukan untuk dukungan masuk kembali yang berhasil.

public void MyMethod()
{
  this.SomeNonLocalDataState;
  // Here you need to clean nonlocal state for other users
  OutboundProxy proxy = new OutboundProxy();
  int returnValue = proxy.CallOutOfOperation();
  // Ensure that this.SomeNonLocalDataState is valid for continued use.
  this.ModifyNonLocalState;
  return returnValue;
}

Menggunakan pola panggilan asinkron Mulai/Akhir untuk panggilan keluar saat ConcurrencyMode memicu Reentrant pengecualian. Panggilan keluar asinkron memerlukan operasi di mana ConcurrencyMode adalah , dalam hal ini MultipleAnda harus menangani masalah sinkronisasi.

Umumnya, jika pesan tiba untuk instans yang melanggar mode konkurensinya, pesan menunggu hingga instans tersedia, atau sampai waktu habis.

Selain itu, jika ConcurrencyMode diatur ke Single dan panggilan masuk kembali diblokir saat menunggu instans dibebaskan, sistem mendeteksi kebuntuan dan melemparkan pengecualian.

Nota

InvalidOperationException dilemparkan pada waktu proses jika ReleaseServiceInstanceOnTransactionComplete adalah true ketika ConcurrencyMode properti diatur ke Single.

Perhatikan bahwa Anda harus secara eksplisit mengatur ReleaseServiceInstanceOnTransactionComplete ke false jika ada operasi dengan OperationBehaviorAttribute.TransactionScopeRequired diatur ke true dan Anda mengatur ConcurrencyMode ke Reentrant. Jika tidak, pengecualian validasi dilemparkan karena nilai ReleaseServiceInstanceOnTransactionComplete defaultnya adalah true.

Ada interaksi properti ConcurrencyMode dan lainnya yang dapat mengubah perilaku runtime. Untuk deskripsi lengkap interaksi ini, lihat Sesi, Instancing, dan Konkurensi.

Berlaku untuk