I/O操作同步与异步

I/O操作是指输入/输出操作,是计算机与外部设备(如硬盘、网络、用户输入设备等)之间进行数据交换的过程。I/O操作包括多种类型,涵盖了文件操作、网络通信、内存操作和控制台交互等。

同步I/O操作是指程序在执行I/O操作时必须等待操作完成才能继续执行后续的代码。同步I/O操作的优点是简单直观,易于理解和实现,但缺点是效率较低,因为程序的执行会因为等待I/O操作而被阻塞。

异步I/O操作是指程序在执行I/O操作时,可以不等待操作完成,而是继续执行后续的代码。当I/O操作完成后,系统会通过回调函数、事件通知等方式告诉程序。异步I/O操作的优点是可以提高程序的执行效率,特别是在需要处理大量I/O操作的情况下,因为程序可以在等待I/O操作完成的同时执行其他任务。异步I/O操作的方法包括但不限于:

  1. 回调函数:当I/O操作完成后,调用预先定义好的回调函数。
  2. 事件驱动:程序通过监听事件来了解I/O操作的状态。
  3. 信号量:通过信号量控制程序的执行流程,当I/O操作完成时,释放信号量,程序可以继续执行。
  4. 通知机制:例如Linux中的inotify,可以监控文件系统的变化。
  5. 线程和协程:使用多线程或多协程的方式,一个线程或协程负责I/O操作,其他线程或协程可以继续执行其他任务。

这些方法可以单独使用,也可以结合使用,以达到最佳的程序性能。

下面是分别使用同步和异步方式进行文件I/O和网络I/O操作的详细示例。

文件I/O操作

同步文件写入

使用StreamWriter类进行同步文件写入操作:

using System;
using System.IO;

class SyncFileWriteExample
{
    static void Main()
    {
        string filePath = "sync_example.txt";
        string content = "这是一个同步文件写入的示例。";

        // 使用 StreamWriter 同步写入文件
        using (StreamWriter writer = new StreamWriter(filePath))
        {
            writer.WriteLine(content);
        }

        Console.WriteLine("同步文件写入完成。");
    }
}

异步文件写入

使用StreamWriter类进行异步文件写入操作:

using System;
using System.IO;
using System.Threading.Tasks;

class AsyncFileWriteExample
{
    static async Task Main()
    {
        string filePath = "async_example.txt";
        string content = "这是一个异步文件写入的示例。";

        // 使用 StreamWriter 异步写入文件
        using (StreamWriter writer = new StreamWriter(filePath))
        {
            await writer.WriteLineAsync(content);
        }

        Console.WriteLine("异步文件写入完成。");
    }
}

同步文件读取

使用StreamReader类进行同步文件读取操作:

using System;
using System.IO;

class SyncFileReadExample
{
    static void Main()
    {
        string filePath = "sync_example.txt";

        // 使用 StreamReader 同步读取文件
        if (File.Exists(filePath))
        {
            using (StreamReader reader = new StreamReader(filePath))
            {
                string content = reader.ReadToEnd();
                Console.WriteLine("同步读取的文件内容:");
                Console.WriteLine(content);
            }
        }
        else
        {
            Console.WriteLine("文件不存在。");
        }
    }
}

CopyInsert

异步文件读取

使用StreamReader类进行异步文件读取操作:

using System;
using System.IO;
using System.Threading.Tasks;

class AsyncFileReadExample
{
    static async Task Main()
    {
        string filePath = "async_example.txt";

        // 使用 StreamReader 异步读取文件
        if (File.Exists(filePath))
        {
            using (StreamReader reader = new StreamReader(filePath))
            {
                string content = await reader.ReadToEndAsync();
                Console.WriteLine("异步读取的文件内容:");
                Console.WriteLine(content);
            }
        }
        else
        {
            Console.WriteLine("文件不存在。");
        }
    }
}

网络I/O操作

同步网络发送数据

使用TcpClient类进行同步网络发送数据:

using System;
using System.Net.Sockets;
using System.Text;

class SyncTcpClientExample
{
    static void Main()
    {
        TcpClient client = new TcpClient();

        try
        {
            client.Connect("127.0.0.1", 5000);
            NetworkStream stream = client.GetStream();

            // 同步发送数据
            string message = "Hello, Server!";
            byte[] data = Encoding.ASCII.GetBytes(message);
            stream.Write(data, 0, data.Length);

            Console.WriteLine("同步发送消息到服务器完成。");

            // 同步接收响应
            data = new byte[256];
            int bytesRead = stream.Read(data, 0, data.Length);
            string response = Encoding.ASCII.GetString(data, 0, bytesRead);
            Console.WriteLine("服务器响应: " + response);
        }
        catch (Exception e)
        {
            Console.WriteLine("异常: " + e.Message);
        }
        finally
        {
            client.Close();
        }
    }
}

异步网络发送数据

使用TcpClient类进行异步网络发送数据:

using System;
using System.Net.Sockets;
using System.Text;
using System.Threading.Tasks;

class AsyncTcpClientExample
{
    static async Task Main()
    {
        TcpClient client = new TcpClient();

        try
        {
            await client.ConnectAsync("127.0.0.1", 5000);
            NetworkStream stream = client.GetStream();

            // 异步发送数据
            string message = "Hello, Server!";
            byte[] data = Encoding.ASCII.GetBytes(message);
            await stream.WriteAsync(data, 0, data.Length);

            Console.WriteLine("异步发送消息到服务器完成。");

            // 异步接收响应
            data = new byte[256];
            int bytesRead = await stream.ReadAsync(data, 0, data.Length);
            string response = Encoding.ASCII.GetString(data, 0, bytesRead);
            Console.WriteLine("服务器响应: " + response);
        }
        catch (Exception e)
        {
            Console.WriteLine("异常: " + e.Message);
        }
        finally
        {
            client.Close();
        }
    }
}

同步网络接收数据

使用TcpListener类进行同步网络接收数据:

using System;
using System.Net;
using System.Net.Sockets;
using System.Text;

class SyncTcpServerExample
{
    static void Main()
    {
        TcpListener server = new TcpListener(IPAddress.Any, 5000);
        server.Start();

        Console.WriteLine("等待客户端连接...");

        // 同步接受客户端连接
        TcpClient client = server.AcceptTcpClient();
        Console.WriteLine("客户端已连接。");

        NetworkStream stream = client.GetStream();

        byte[] buffer = new byte[256];
        int bytesRead;

        // 同步从客户端接收数据
        while ((bytesRead = stream.Read(buffer, 0, buffer.Length)) != 0)
        {
            string receivedData = Encoding.ASCII.GetString(buffer, 0, bytesRead);
            Console.WriteLine("接收到的数据: " + receivedData);

            // 同步发送响应到客户端
            string response = "Hello, Client!";
            byte[] responseData = Encoding.ASCII.GetBytes(response);
            stream.Write(responseData, 0, responseData.Length);
        }

        client.Close();
        server.Stop();
    }
}

异步网络接收数据

使用TcpListener类进行异步网络接收数据:

using System;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading.Tasks;

class AsyncTcpServerExample
{
    static async Task Main()
    {
        TcpListener server = new TcpListener(IPAddress.Any, 5000);
        server.Start();

        Console.WriteLine("等待客户端连接...");

        // 异步接受客户端连接
        TcpClient client = await server.AcceptTcpClientAsync();
        Console.WriteLine("客户端已连接。");

        NetworkStream stream = client.GetStream();

        byte[] buffer = new byte[256];
        int bytesRead;

        // 异步从客户端接收数据
        while ((bytesRead = await stream.ReadAsync(buffer, 0, buffer.Length)) != 0)
        {
            string receivedData = Encoding.ASCII.GetString(buffer, 0, bytesRead);
            Console.WriteLine("接收到的数据: " + receivedData);

            // 异步发送响应到客户端
            string response = "Hello, Client!";
            byte[] responseData = Encoding.ASCII.GetBytes(response);
            await stream.WriteAsync(responseData, 0, responseData.Length);
        }

        client.Close();
        server.Stop();
    }
}

内存I/O操作

同步内存写入

使用MemoryStream类进行同步内存写入操作:

using System;
using System.IO;

class SyncMemoryWriteExample
{
    static void Main()
    {
        using (MemoryStream memoryStream = new MemoryStream())
        {
            // 同步写入数据到内存流
            string message = "这是一个同步内存写入的示例。";
            byte[] data = System.Text.Encoding.ASCII.GetBytes(message);
            memoryStream.Write(data, 0, data.Length);

            // 将流的位置重置到开始
            memoryStream.Seek(0, SeekOrigin.Begin);

            // 从内存流中读取数据
            byte[] buffer = new byte[data.Length];
            int bytesRead = memoryStream.Read(buffer, 0, buffer.Length);
            string receivedData = System.Text.Encoding.ASCII.GetString(buffer, 0, bytesRead);

            Console.WriteLine("从内存流中读取的数据: " + receivedData);
        }
    }
}

CopyInsert

异步内存写入

使用MemoryStream类进行异步内存写入操作:

using System;
using System.IO;
using System.Threading.Tasks;

class AsyncMemoryWriteExample
{
    static async Task Main()
    {
        using (MemoryStream memoryStream = new MemoryStream())
        {
            // 异步写入数据到内存流
            string message = "这是一个异步内存写入的示例。";
            byte[] data = System.Text.Encoding.ASCII.GetBytes(message);
            await memoryStream.WriteAsync(data, 0, data.Length);

            // 将流的位置重置到开始
            memoryStream.Seek(0, SeekOrigin.Begin);

            // 从内存流中读取数据
            byte[] buffer = new byte[data.Length];
            int bytesRead = await memoryStream.ReadAsync(buffer, 0, buffer.Length);
            string receivedData = System.Text.Encoding.ASCII.GetString(buffer, 0, bytesRead);

            Console.WriteLine("从内存流中读取的数据: " + receivedData);
        }
    }
}

控制台I/O操作

同步控制台输入

使用Console.ReadLine方法进行同步控制台输入操作:

using System;

class SyncConsoleInputExample
{
    static void Main()
    {
        Console.WriteLine("请输入一些文本:");
        string userInput = Console.ReadLine();

        Console.WriteLine("你输入的文本是: " + userInput);
    }
}

异步控制台输入

C#的Console类没有直接提供异步方法来读取输入,但可以使用Task.Run来实现异步效果:

using System;
using System.Threading.Tasks;

class AsyncConsoleInputExample
{
    static async Task Main()
    {
        Console.WriteLine("请输入一些文本:");
        Task<string> readTask = Task.Run(() => Console.ReadLine());

        string userInput = await readTask;
        Console.WriteLine("你输入的文本是: " + userInput);
    }
}

数据库I/O操作

在C#中,数据库I/O操作通常涉及使用ADO.NET或其他ORM(对象关系映射)框架(如Entity Framework)与数据库进行交互。

  • 同步数据库操作:直接调用同步方法(如 ExecuteNonQueryExecuteReaderSaveChanges),会阻塞当前线程,直到操作完成。
  • 异步数据库操作:调用异步方法(如 ExecuteNonQueryAsyncExecuteReaderAsyncSaveChangesAsync),不会阻塞当前线程,允许程序在等待数据库操作完成的同时执行其他任务。

使用 ADO.NET 进行数据库I/O操作

ADO.NET 提供了 SqlConnectionSqlCommand 等类来与数据库进行交互。我们可以通过这些类的同步和异步方法来执行数据库操作。

同步数据库写入操作

使用 SqlCommand 进行同步数据库写入操作:

using System;
using System.Data.SqlClient;

class SyncDatabaseWriteExample
{
    static void Main()
    {
        string connectionString = "Server=(localdb)\\mssqllocaldb;Database=TestDB;Integrated Security=True;";
        string query = "INSERT INTO Users (Name, Age) VALUES (@Name, @Age)";

        using (SqlConnection connection = new SqlConnection(connectionString))
        {
            connection.Open();

            using (SqlCommand command = new SqlCommand(query, connection))
            {
                command.Parameters.AddWithValue("@Name", "Alice");
                command.Parameters.AddWithValue("@Age", 30);

                // 同步执行插入操作
                int rowsAffected = command.ExecuteNonQuery();
                Console.WriteLine("同步数据库写入完成,影响的行数: " + rowsAffected);
            }
        }
    }
}

异步数据库写入操作

使用 SqlCommand 进行异步数据库写入操作:

using System;
using System.Data.SqlClient;
using System.Threading.Tasks;

class AsyncDatabaseWriteExample
{
    static async Task Main()
    {
        string connectionString = "Server=(localdb)\\mssqllocaldb;Database=TestDB;Integrated Security=True;";
        string query = "INSERT INTO Users (Name, Age) VALUES (@Name, @Age)";

        using (SqlConnection connection = new SqlConnection(connectionString))
        {
            await connection.OpenAsync();

            using (SqlCommand command = new SqlCommand(query, connection))
            {
                command.Parameters.AddWithValue("@Name", "Bob");
                command.Parameters.AddWithValue("@Age", 25);

                // 异步执行插入操作
                int rowsAffected = await command.ExecuteNonQueryAsync();
                Console.WriteLine("异步数据库写入完成,影响的行数: " + rowsAffected);
            }
        }
    }
}

同步数据库读取操作

使用 SqlCommand 进行同步数据库读取操作:

using System;
using System.Data.SqlClient;

class SyncDatabaseReadExample
{
    static void Main()
    {
        string connectionString = "Server=(localdb)\\mssqllocaldb;Database=TestDB;Integrated Security=True;";
        string query = "SELECT Name, Age FROM Users";

        using (SqlConnection connection = new SqlConnection(connectionString))
        {
            connection.Open();

            using (SqlCommand command = new SqlCommand(query, connection))
            {
                using (SqlDataReader reader = command.ExecuteReader())
                {
                    // 读取数据
                    while (reader.Read())
                    {
                        string name = reader.GetString(0);
                        int age = reader.GetInt32(1);
                        Console.WriteLine($"同步读取的数据: Name = {name}, Age = {age}");
                    }
                }
            }
        }
    }
}

异步数据库读取操作

使用 SqlCommand 进行异步数据库读取操作:

using System;
using System.Data.SqlClient;
using System.Threading.Tasks;

class AsyncDatabaseReadExample
{
    static async Task Main()
    {
        string connectionString = "Server=(localdb)\\mssqllocaldb;Database=TestDB;Integrated Security=True;";
        string query = "SELECT Name, Age FROM Users";

        using (SqlConnection connection = new SqlConnection(connectionString))
        {
            await connection.OpenAsync();

            using (SqlCommand command = new SqlCommand(query, connection))
            {
                using (SqlDataReader reader = await command.ExecuteReaderAsync())
                {
                    // 异步读取数据
                    while (await reader.ReadAsync())
                    {
                        string name = reader.GetString(0);
                        int age = reader.GetInt32(1);
                        Console.WriteLine($"异步读取的数据: Name = {name}, Age = {age}");
                    }
                }
            }
        }
    }
}

使用 Entity Framework 进行数据库I/O操作

Entity Framework 是一个ORM框架,可以简化数据库操作。我们可以通过其同步和异步方法来执行数据库操作。

同步数据库写入操作

使用 Entity Framework 进行同步数据库写入操作:

using System;
using System.Linq;
using Microsoft.EntityFrameworkCore;

class SyncDatabaseWriteEFExample
{
    static void Main()
    {
        using (var context = new TestDbContext())
        {
            var user = new User { Name = "Charlie", Age = 35 };
            context.Users.Add(user);

            // 同步保存更改
            int rowsAffected = context.SaveChanges();
            Console.WriteLine("同步数据库写入完成,影响的行数: " + rowsAffected);
        }
    }
}

public class TestDbContext : DbContext
{
    public DbSet<User> Users { get; set; }

    protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
    {
        optionsBuilder.UseSqlServer("Server=(localdb)\\mssqllocaldb;Database=TestDB;Integrated Security=True;");
    }
}

public class User
{
    public int Id { get; set; }
    public string Name { get; set; }
    public int Age { get; set; }
}

异步数据库写入操作

使用 Entity Framework 进行异步数据库写入操作:

using System;
using System.Threading.Tasks;
using Microsoft.EntityFrameworkCore;

class AsyncDatabaseWriteEFExample
{
    static async Task Main()
    {
        using (var context = new TestDbContext())
        {
            var user = new User { Name = "David", Age = 40 };
            context.Users.Add(user);

            // 异步保存更改
            int rowsAffected = await context.SaveChangesAsync();
            Console.WriteLine("异步数据库写入完成,影响的行数: " + rowsAffected);
        }
    }
}

public class TestDbContext : DbContext
{
    public DbSet<User> Users { get; set; }

    protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
    {
        optionsBuilder.UseSqlServer("Server=(localdb)\\mssqllocaldb;Database=TestDB;Integrated Security=True;");
    }
}

public class User
{
    public int Id { get; set; }
    public string Name { get; set; }
    public int Age { get; set; }
}

同步数据库读取操作

使用 Entity Framework 进行同步数据库读取操作:

using System;
using System.Linq;
using Microsoft.EntityFrameworkCore;

class SyncDatabaseReadEFExample
{
    static void Main()
    {
        using (var context = new TestDbContext())
        {
            var users = context.Users.ToList();

            // 读取数据
            foreach (var user in users)
            {
                Console.WriteLine($"同步读取的数据: Id = {user.Id}, Name = {user.Name}, Age = {user.Age}");
            }
        }
    }
}

public class TestDbContext : DbContext
{
    public DbSet<User> Users { get; set; }

    protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
    {
        optionsBuilder.UseSqlServer("Server=(localdb)\\mssqllocaldb;Database=TestDB;Integrated Security=True;");
    }
}

public class User
{
    public int Id { get; set; }
    public string Name { get; set; }
    public int Age { get; set; }
}

异步数据库读取操作

使用 Entity Framework 进行异步数据库读取操作:

using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using Microsoft.EntityFrameworkCore;

class AsyncDatabaseReadEFExample
{
    static async Task Main()
    {
        using (var context = new TestDbContext())
        {
            var users = await context.Users.ToListAsync();

            // 异步读取数据
            foreach (var user in users)
            {
                Console.WriteLine($"异步读取的数据: Id = {user.Id}, Name = {user.Name}, Age = {user.Age}");
            }
        }
    }
}

public class TestDbContext : DbContext
{
    public DbSet<User> Users { get; set; }

    protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
    {
        optionsBuilder.UseSqlServer("Server=(localdb)\\mssqllocaldb;Database=TestDB;Integrated Security=True;");
    }
}

public class User
{
    public int Id { get; set; }
    public string Name { get; set; }
    public int Age { get; set; }
}

总结

  • 同步I/O操作:阻塞当前线程,直到操作完成。适用于I/O操作时间较短的情况,可以简化代码逻辑。
  • 异步I/O操作:不阻塞当前线程,允许程序在等待I/O操作完成的同时执行其他任务。适用于I/O操作时间较长的情况,可以提高程序的响应性和性能。

通过这些示例,你可以看到同步和异步I/O操作在C#中的具体实现方式和差异。

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值