İzlenecek Yol: Aracı Temelli Uygulama Oluşturma
Bu konu başlığında, temel aracı tabanlı bir uygulamanın nasıl oluşturulacağı açıklanmaktadır. Bu kılavuzda, bir metin dosyasındaki verileri zaman uyumsuz olarak okuyan bir aracı oluşturabilirsiniz. Uygulama, söz konusu dosyanın içeriğinin sağlama toplamını hesaplamak için Adler-32 sağlama toplamı algoritmasını kullanır.
Ön koşullar
Bu kılavuzu tamamlamak için aşağıdaki konuları anlamanız gerekir:
Bölümler
Bu kılavuzda aşağıdaki görevlerin nasıl gerçekleştirebileceğiniz gösterilmektedir:
Konsol Uygulaması Oluşturma
Bu bölümde, programın kullanacağı üst bilgi dosyalarına başvuran bir C++ konsol uygulamasının nasıl oluşturulacağı gösterilmektedir. İlk adımlar, hangi Visual Studio sürümünü kullandığınıza bağlı olarak değişir. Tercih ettiğiniz Visual Studio sürümünün belgelerini görmek için Sürüm seçici denetimini kullanın. Bu sayfadaki içindekiler tablosunun en üstünde bulunur.
Visual Studio'da C++ konsol uygulaması oluşturmak için
Ana menüden Dosya>Yeni Proje'yi seçerek Yeni>Proje Oluştur iletişim kutusunu açın.
İletişim kutusunun üst kısmında Dil'i C++ olarak, Platform'ı Windows olarak ve Proje türü'nü Konsol olarak ayarlayın.
Filtrelenen proje türleri listesinden Konsol Uygulaması'nı ve ardından İleri'yi seçin. Sonraki sayfada, projenin adı olarak girin
BasicAgent
ve isterseniz proje konumunu belirtin.Projeyi oluşturmak için Oluştur düğmesini seçin.
Çözüm Gezgini proje düğümüne sağ tıklayın ve Özellikler'i seçin. Yapılandırma Özellikleri>C/C++>Önceden Derlenmiş Üst Bilgiler>Önceden Derlenmiş üst bilgi altında Oluştur'u seçin.
Visual Studio 2017 ve önceki sürümlerde C++ konsol uygulaması oluşturmak için
Dosya menüsünde Yeni'ye tıklayın ve ardından Yeni Proje iletişim kutusunu görüntülemek için Proje'ye tıklayın.
Yeni Proje iletişim kutusunda, Proje türleri bölmesinde Visual C++ düğümünü seçin ve ardından Şablonlar bölmesinde Win32 Konsol Uygulaması'nıseçin. Proje için örneğin,
BasicAgent
bir ad yazın ve Win32 Konsol Uygulaması Sihirbazı'nı görüntülemek için Tamam'a tıklayın.Win32 Konsol Uygulaması Sihirbazı iletişim kutusunda Son'a tıklayın.
Üst bilgi dosyasını güncelleştirme
pch.h (Visual Studio 2017 ve önceki sürümlerde stdafx.h) dosyasına aşağıdaki kodu ekleyin:
#include <agents.h>
#include <string>
#include <iostream>
#include <algorithm>
agents.h üst bilgisi, concurrency::agent sınıfının işlevselliğini içerir.
Uygulamayı doğrulama
Son olarak, uygulamanın oluşturup çalıştırarak başarıyla oluşturulduğunu doğrulayın. Uygulamayı derlemek için, Derleme menüsünde Çözüm Oluştur'a tıklayın. Uygulama başarıyla derleniyorsa, Hata Ayıklama menüsünde Hata Ayıklamayı Başlat'a tıklayarak uygulamayı çalıştırın.
[Üst]
file_reader Sınıfı Oluşturma
Bu bölümde sınıfın nasıl oluşturulacağı gösterilmektedir file_reader
. Çalışma zamanı, her aracıyı kendi bağlamında iş gerçekleştirmek üzere zamanlar. Bu nedenle, zaman uyumlu bir şekilde iş gerçekleştiren ancak diğer bileşenlerle zaman uyumsuz olarak etkileşim kuran bir aracı oluşturabilirsiniz. sınıfı, file_reader
belirli bir giriş dosyasındaki verileri okur ve bu dosyadan belirli bir hedef bileşene veri gönderir.
File_reader sınıfını oluşturmak için
Projenize yeni bir C++ üst bilgi dosyası ekleyin. Bunu yapmak için, Çözüm Gezgini Üst Bilgi Dosyaları düğümüne sağ tıklayın, Ekle'ye ve ardından Yeni Öğe'ye tıklayın. Şablonlar bölmesinde Üst Bilgi Dosyası (.h) öğesini seçin. Yeni Öğe Ekle iletişim kutusunda, Ad kutusuna yazın
file_reader.h
ve Ekle'ye tıklayın.file_reader.h dosyasında aşağıdaki kodu ekleyin.
#pragma once
file_reader.h dosyasından
agent
türetilen adlıfile_reader
bir sınıf oluşturun.class file_reader : public concurrency::agent { public: protected: private: };
Aşağıdaki veri üyelerini
private
sınıfınızın bölümüne ekleyin.std::string _file_name; concurrency::ITarget<std::string>& _target; concurrency::overwrite_buffer<std::exception> _error;
Üye
_file_name
, aracının okuduğu dosya adıdır. Üye_target
, aracının dosyanın içeriğini yazdığı eşzamanlılık ::ITarget nesnesidir. Üye,_error
aracının ömrü boyunca oluşan herhangi bir hatayı tutar.Oluşturucular için
file_reader
aşağıdaki kodu sınıfınpublic
file_reader
bölümüne ekleyin.explicit file_reader(const std::string& file_name, concurrency::ITarget<std::string>& target) : _file_name(file_name) , _target(target) { } explicit file_reader(const std::string& file_name, concurrency::ITarget<std::string>& target, concurrency::Scheduler& scheduler) : agent(scheduler) , _file_name(file_name) , _target(target) { } explicit file_reader(const std::string& file_name, concurrency::ITarget<std::string>& target, concurrency::ScheduleGroup& group) : agent(group) , _file_name(file_name) , _target(target) { }
Her oluşturucu aşırı yüklemesi veri üyelerini
file_reader
ayarlar. İkinci ve üçüncü oluşturucu aşırı yüklemesi, uygulamanızın aracınızla belirli bir zamanlayıcı kullanmasını sağlar. İlk aşırı yükleme aracınızla varsayılan zamanlayıcıyı kullanır.get_error
yöntemini sınıfın genel bölümünefile_reader
ekleyin.bool get_error(std::exception& e) { return try_receive(_error, e); }
yöntemi,
get_error
aracının ömrü boyunca oluşan tüm hataları alır.Sınıfınızın bölümünde concurrency::agent::run yöntemini
protected
uygulayın.void run() { FILE* stream; try { // Open the file. if (fopen_s(&stream, _file_name.c_str(), "r") != 0) { // Throw an exception if an error occurs. throw std::exception("Failed to open input file."); } // Create a buffer to hold file data. char buf[1024]; // Set the buffer size. setvbuf(stream, buf, _IOFBF, sizeof buf); // Read the contents of the file and send the contents // to the target. while (fgets(buf, sizeof buf, stream)) { asend(_target, std::string(buf)); } // Send the empty string to the target to indicate the end of processing. asend(_target, std::string("")); // Close the file. fclose(stream); } catch (const std::exception& e) { // Send the empty string to the target to indicate the end of processing. asend(_target, std::string("")); // Write the exception to the error buffer. send(_error, e); } // Set the status of the agent to agent_done. done(); }
run
yöntemi dosyayı açar ve ondan verileri okur. yöntemi, run
dosya işleme sırasında oluşan hataları yakalamak için özel durum işlemeyi kullanır.
Bu yöntem dosyadaki verileri her okuduğunda, bu verileri hedef arabelleğe göndermek için eşzamanlılık::asend işlevini çağırır. İşlem sonunu belirtmek için boş dizeyi hedef arabelleğine gönderir.
Aşağıdaki örnekte file_reader.h dosyasının tüm içeriği gösterilmektedir.
#pragma once
class file_reader : public concurrency::agent
{
public:
explicit file_reader(const std::string& file_name,
concurrency::ITarget<std::string>& target)
: _file_name(file_name)
, _target(target)
{
}
explicit file_reader(const std::string& file_name,
concurrency::ITarget<std::string>& target,
concurrency::Scheduler& scheduler)
: agent(scheduler)
, _file_name(file_name)
, _target(target)
{
}
explicit file_reader(const std::string& file_name,
concurrency::ITarget<std::string>& target,
concurrency::ScheduleGroup& group)
: agent(group)
, _file_name(file_name)
, _target(target)
{
}
// Retrieves any error that occurs during the life of the agent.
bool get_error(std::exception& e)
{
return try_receive(_error, e);
}
protected:
void run()
{
FILE* stream;
try
{
// Open the file.
if (fopen_s(&stream, _file_name.c_str(), "r") != 0)
{
// Throw an exception if an error occurs.
throw std::exception("Failed to open input file.");
}
// Create a buffer to hold file data.
char buf[1024];
// Set the buffer size.
setvbuf(stream, buf, _IOFBF, sizeof buf);
// Read the contents of the file and send the contents
// to the target.
while (fgets(buf, sizeof buf, stream))
{
asend(_target, std::string(buf));
}
// Send the empty string to the target to indicate the end of processing.
asend(_target, std::string(""));
// Close the file.
fclose(stream);
}
catch (const std::exception& e)
{
// Send the empty string to the target to indicate the end of processing.
asend(_target, std::string(""));
// Write the exception to the error buffer.
send(_error, e);
}
// Set the status of the agent to agent_done.
done();
}
private:
std::string _file_name;
concurrency::ITarget<std::string>& _target;
concurrency::overwrite_buffer<std::exception> _error;
};
[Üst]
Uygulamadaki file_reader Sınıfını Kullanma
Bu bölümde, bir metin dosyasının file_reader
içeriğini okumak için sınıfın nasıl kullanılacağı gösterilmektedir. Ayrıca bu dosya verilerini alan ve Adler-32 sağlama toplamını hesaplayan concurrency ::call nesnesinin nasıl oluşturulacağını da gösterir.
File_reader sınıfını Uygulamanızda kullanmak için
BasicAgent.cpp dosyasında aşağıdaki
#include
deyimi ekleyin.#include "file_reader.h"
BasicAgent.cpp dosyasında aşağıdaki
using
yönergeleri ekleyin.using namespace concurrency; using namespace std;
işlevinde
_tmain
, işlemenin sona erdiğini belirten bir concurrency::event nesnesi oluşturun.event e;
Veri aldığında sağlama toplamını güncelleştiren bir
call
nesne oluşturun.// The components of the Adler-32 sum. unsigned int a = 1; unsigned int b = 0; // A call object that updates the checksum when it receives data. call<string> calculate_checksum([&] (string s) { // If the input string is empty, set the event to signal // the end of processing. if (s.size() == 0) e.set(); // Perform the Adler-32 checksum algorithm. for_each(begin(s), end(s), [&] (char c) { a = (a + c) % 65521; b = (b + a) % 65521; }); });
Bu
call
nesne, boş dizeyi aldığında da işlemenin sonuna işaret etmek için nesnesini ayarlarevent
.test.txt dosyasından okuyan ve bu dosyanın içeriğini nesneye
call
yazan birfile_reader
nesne oluşturun.file_reader reader("test.txt", calculate_checksum);
Aracıyı başlatın ve bitmesini bekleyin.
reader.start(); agent::wait(&reader);
Nesnenin
call
tüm verileri almasını ve tamamlanmasını bekleyin.e.wait();
Dosya okuyucuda hatalar olup olmadığını denetleyin. Hata oluşmadıysa, son Adler-32 toplamını hesaplayın ve toplamı konsola yazdırın.
std::exception error; if (reader.get_error(error)) { wcout << error.what() << endl; } else { unsigned int adler32_sum = (b << 16) | a; wcout << L"Adler-32 sum is " << hex << adler32_sum << endl; }
Aşağıdaki örnekte BasicAgent.cpp dosyasının tamamı gösterilmektedir.
// BasicAgent.cpp : Defines the entry point for the console application.
//
#include "pch.h" // Use stdafx.h in Visual Studio 2017 and earlier
#include "file_reader.h"
using namespace concurrency;
using namespace std;
int _tmain(int argc, _TCHAR* argv[])
{
// An event object that signals the end of processing.
event e;
// The components of the Adler-32 sum.
unsigned int a = 1;
unsigned int b = 0;
// A call object that updates the checksum when it receives data.
call<string> calculate_checksum([&] (string s) {
// If the input string is empty, set the event to signal
// the end of processing.
if (s.size() == 0)
e.set();
// Perform the Adler-32 checksum algorithm.
for_each(begin(s), end(s), [&] (char c) {
a = (a + c) % 65521;
b = (b + a) % 65521;
});
});
// Create the agent.
file_reader reader("test.txt", calculate_checksum);
// Start the agent and wait for it to complete.
reader.start();
agent::wait(&reader);
// Wait for the call object to receive all data and complete.
e.wait();
// Check the file reader for errors.
// If no error occurred, calculate the final Adler-32 sum and print it
// to the console.
std::exception error;
if (reader.get_error(error))
{
wcout << error.what() << endl;
}
else
{
unsigned int adler32_sum = (b << 16) | a;
wcout << L"Adler-32 sum is " << hex << adler32_sum << endl;
}
}
[Üst]
Örnek Giriş
Bu, text.txt giriş dosyasının örnek içeriğidir:
The quick brown fox
jumps
over the lazy dog
Örnek Çıkış
Örnek girişle kullanıldığında, bu program aşağıdaki çıkışı üretir:
Adler-32 sum is fefb0d75
Güçlü Programlama
Veri üyelerine eşzamanlı erişimi önlemek için, sınıfınızın veya private
bölümüne iş protected
gerçekleştiren yöntemler eklemenizi öneririz. Yalnızca aracıya veya aracıdan public
ileti gönderen veya alan yöntemleri sınıfınızın bölümüne ekleyin.
Aracınızı tamamlanmış duruma taşımak için her zaman concurrency::agent::d one yöntemini çağırın. Yönteminden run
dönmeden önce genellikle bu yöntemi çağırırsınız.
Sonraki Adımlar
Aracı tabanlı bir uygulamanın başka bir örneği için bkz . İzlenecek yol: Kilitlenmeyi Önlemek için birleştirmeyi kullanma.
Ayrıca bkz.
Zaman Uyumsuz Aracılar Kitaplığı
Zaman Uyumsuz İleti Blokları
İleti Geçirme İşlevleri
Eşitleme Veri Yapıları
İzlenecek Yol: Kilitlenmeyi Önlemek için birleştirme kullanma
Geri Bildirim
https://aka.ms/ContentUserFeedback.
Çok yakında: 2024 boyunca, içerik için geri bildirim mekanizması olarak GitHub Sorunları’nı kullanımdan kaldıracak ve yeni bir geri bildirim sistemiyle değiştireceğiz. Daha fazla bilgi için bkz.Gönderin ve geri bildirimi görüntüleyin