GetqueueStatus

本文介绍了一种使用异步IO和多线程进行高效文件复制的方法,通过创建IO完成端口(IOCP)来实现跨文件系统的快速复制任务。此方法能够充分利用系统资源,减少等待时间和提高复制速度。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

#include "stdafx.h"
#include <Windows.h>
#include <process.h>
#include <iostream>
using namespace std;


//完成键
#define CK_READ  1
#define CK_WRITE 2


void ShowErrMsg(LPCSTR lpMsg); 


//传给线程函数的参数
typedef struct _tagThreadParam
{
    HANDLE hIOCP;                //IOCP
    LPVOID lpAddr;                //读入的内存地址
    LARGE_INTEGER liFileSize;   //源文件大小
    size_t nDataBlockSize;      //每次读写的数据块大小
    HANDLE hSrc;                //源文件
    HANDLE hDest;                //目的文件
    LPOVERLAPPED lpOLPSrc;      //源文件的OVERLAPPED结构指针
    LPOVERLAPPED lpOLPDest;     //目的文件的OVERLAPPED结构指针
}ThreadParam, *LPTHREADPARAM;


int _tmain(int argc, _TCHAR* argv[])
{
   /*LPCTSTR lpSrc = TEXT("D:\\SourceSoftware\\myeclipse-8.5.0.rar");
      LPCTSTR lpDest = TEXT("D:\\SourceSoftware\\myeclipse-8.5.0_copy.rar");*/ 


    /*LPCTSTR lpSrc = TEXT("D:\\SourceSoftware\\VS2010\\cn_visual_studio_2010_ultimate_x86_dvd_532347.iso");
    LPCTSTR lpDest = TEXT("D:\\SourceSoftware\\VS2010\\cn_visual_studio_2010_ultimate_x86_dvd_532347_copy.iso");*/ 


    /*LPCTSTR lpSrc = TEXT("D:\\SourceSoftware\\SQLServer2008\\cn_sql_server_2008_r2_developer_x86_x64_ia64_dvd_522724.iso");
    LPCTSTR lpDest = TEXT("D:\\SourceSoftware\\SQLServer2008\\cn_sql_server_2008_r2_developer_x86_x64_ia64_dvd_522724_copy.iso");
*/
    /*LPCTSTR lpSrc = TEXT("D:\\SourceSoftware\\SQLServer2008\\cn_sql_server_2008_r2_developer_x86_x64_ia64_dvd_522724.rar");
    LPCTSTR lpDest = TEXT("D:\\SourceSoftware\\SQLServer2008\\cn_sql_server_2008_r2_developer_x86_x64_ia64_dvd_522724_copy.rar");*/


    


      LPCTSTR lpSrc = TEXT("D:\\SourceSoftware\\VS2012旗舰版\\VS2012_ULT_chs.iso");
      LPCTSTR lpDest = TEXT("D:\\SourceSoftware\\VS2012旗舰版\\VS2012_ULT_chs_copy.iso");




    HANDLE hSrcFile = INVALID_HANDLE_VALUE;  //源文件句柄
    HANDLE hDestFile = INVALID_HANDLE_VALUE; //目标文件句柄
    HANDLE hIOCP = NULL;                     //IOCP
    LPVOID lpAddr = NULL;                     //申请内存地址


    __try
    {
        cout << endl << "开始打开源文件" <<endl;
        //源文件
        hSrcFile = CreateFile(
            lpSrc,                                        //源文件
            GENERIC_READ,                                  //读模式
            FILE_SHARE_READ,                              //读共享
            NULL,                                         //安全属性
            OPEN_EXISTING,                                  //必须存在
            FILE_FLAG_OVERLAPPED | FILE_FLAG_NO_BUFFERING,//异步 | 不用缓存
            NULL                                          //文件模板为空
            );
        if(INVALID_HANDLE_VALUE == hSrcFile)
        {
            ShowErrMsg("源文件打开错误");
            return -1;
        }


        cout << endl << "开始打开目的文件" << endl;


        //目的文件
        hDestFile = CreateFile(
            lpDest,                                        //目的文件
            GENERIC_WRITE,                                 //写模式
            0,                                               //独占访问
            NULL,                                           //安全属性
            CREATE_ALWAYS,                                   //总是创建
            FILE_FLAG_OVERLAPPED | FILE_FLAG_NO_BUFFERING, //异步 | 不用缓存
            hSrcFile                                       //文件属性同源文件
            );
        if (INVALID_HANDLE_VALUE == hDestFile)
        {
            ShowErrMsg("目的文件打开错误");
            return -2;
        }


        cout << endl << "开始获取文件尺寸" << endl;
        //源文件尺寸
        LARGE_INTEGER liFileSize;
        BOOL bRet = GetFileSizeEx(hSrcFile, &liFileSize);
        if (FALSE == bRet)
        {
            ShowErrMsg("获取源文件尺寸失败");
            return -3;
        }


        cout << endl << "开始用源文件尺寸设置目的文件大小" << endl;
        
        //设置目的文件指针位置为源文件尺寸 并 设置文件尾
        BOOL bRet2 = SetFilePointerEx(hDestFile, liFileSize, NULL, FILE_BEGIN);
        BOOL bRet3 = SetEndOfFile(hDestFile);
        if (FALSE == bRet2 || FALSE == bRet3)
        {
            ShowErrMsg("设置目的文件尺寸失败");
            return -4;
        }


        cout << endl << "开始获取磁盘扇区大小 和 系统信息" << endl;
        SYSTEM_INFO sysInfo = {0};
        GetSystemInfo(&sysInfo);
        DWORD dwBytesPerSector = 0UL;
        bRet = GetDiskFreeSpace(TEXT("D:"), NULL, &dwBytesPerSector, NULL, NULL);
        if (FALSE == bRet)
        {
            ShowErrMsg("开始获取磁盘扇区大小 错误");
            return -5;
        }




        //读 
        OVERLAPPED ovlpRead;
        ovlpRead.Offset = 0;
        ovlpRead.OffsetHigh = 0;
        ovlpRead.hEvent = NULL;


        //写
        OVERLAPPED ovlpWrite;
        ovlpWrite.Offset = 0;
        ovlpWrite.OffsetHigh = 0;
        ovlpWrite.hEvent = NULL;


        //创建IOCP 并和 文件关联
        hIOCP = CreateIoCompletionPort(INVALID_HANDLE_VALUE, NULL, 0, sysInfo.dwNumberOfProcessors);
        if (NULL == hIOCP)
        {
            DWORD dwErr = GetLastError();
            if (ERROR_ALREADY_EXISTS != dwErr)
            {
                ShowErrMsg("创建IOCP 失败");
                return -6;
            }
        } 


        hIOCP = CreateIoCompletionPort(hSrcFile, hIOCP, CK_READ, sysInfo.dwNumberOfProcessors);
        hIOCP = CreateIoCompletionPort(hDestFile, hIOCP, CK_WRITE, sysInfo.dwNumberOfProcessors);


        //申请扇区大小的5倍的内存
        size_t sizeMAX = dwBytesPerSector * 1024 * 64 * 2; //512K * 64 * 2
        size_t sizeMIN = dwBytesPerSector * 1024 * 64 * 2; 


        //申请内存
        lpAddr = VirtualAlloc(NULL, sizeMAX, MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE);
        if (NULL == lpAddr)
        {
            ShowErrMsg("申请内存错误");
            return -7;                
        }
         
         
        //先往IOCP的完成队列插入一个 写完成 项
        //写0字节
        PostQueuedCompletionStatus(
            hIOCP,     //IOCP
            0,           //GetQueuedCompletionStatus取到的传送字节为0
            CK_WRITE,  //写操作
            &ovlpWrite //写OVERLAPPED
            );




        DWORD dwBytesTrans = 0;                                    //传输字节数
        ULONG_PTR ulCompleteKey = 0;                            //完成键
        LPOVERLAPPED lpOverlapped = NULL;                        //OVERLAPPED结构
        BOOL bLastTime = FALSE;                                    //最后一个读操作
        int i = 0;
        int j = 0;
        int nCountZero = 0;                                        //计数 




        /************************************************************************/
        /* 因为前一次只是往IOCP的完成队列插入了一项【写完成】,而并非真的写
        只是让下面的代码从 【读操作】开始, 
        执行序列为: 读-写, 读-写, ... ,读-写
        当每个【读操作】完成时:把缓冲区中的数据写入【目的文件】,并更新【源文件】的偏移量




        当每个【写操作】完成时:更新【目的文件】的偏移量,
        同时,因为操作序列是写操作在后,因此写操作完成后,根据更新后的【源文件】的偏移量
        和【源文件】大小做比较,如果大于等于源文件大小,则说明这是最后一次读取操作,则当下一次
        写操作完成时 退出循环。 如果当前【源文件偏移量】没有达到【源文件大小】则再次从【源文件】
        中读取数据进缓冲区,
        /************************************************************************/
        while(TRUE)
        {
            BOOL bRet = GetQueuedCompletionStatus(hIOCP, &dwBytesTrans, &ulCompleteKey, &lpOverlapped, INFINITE);
            if (FALSE == bRet)
            {
                DWORD dwErr = GetLastError();
                if (NULL != lpOverlapped)
                {
                    ShowErrMsg("线程函数返回错误, 错误原因:");
                    cout << dwErr <<endl; 
                    break;
                } //if
                else
                {
                    if (ERROR_TIMEOUT == dwErr)
                    {
                        ShowErrMsg("等待超时"); 
                    }
                    else
                    {
                        ShowErrMsg("线程函数返回错误, 错误原因2:");
                        cout << dwErr <<endl; 
                    }


                    continue;  
                } //else  


            } //if


            //读操作完成 
            if (ulCompleteKey == CK_READ)
            { 
                cout << endl << "-------------第 " << ++ i << " 次操作完成,开始写文件 ---------------- "<<endl;
                WriteFile(hDestFile, lpAddr, sizeMIN, NULL, &ovlpWrite);


                //读操作完成 更新 源文件的偏移量
                LARGE_INTEGER liSrcFile; 
                liSrcFile.QuadPart = dwBytesTrans;


                ovlpRead.Offset += liSrcFile.LowPart;
                ovlpRead.OffsetHigh += liSrcFile.HighPart; 
            } //if


            //写操作完成 
            else if (ulCompleteKey == CK_WRITE)
            {
                //写操作完成, 更新目的文件的偏移量
                LARGE_INTEGER liDestFile;  
                liDestFile.QuadPart = dwBytesTrans;  
                ovlpWrite.Offset += liDestFile.LowPart;
                ovlpWrite.OffsetHigh += liDestFile.HighPart;


                //当前源文件的偏移量 
                LARGE_INTEGER liTemp;
                liTemp.LowPart = ovlpRead.Offset;
                liTemp.HighPart = ovlpRead.OffsetHigh;
                //当前文件偏移是超过文件大小
                if (liTemp.QuadPart >= liFileSize.QuadPart)
                {
                    break;
                }  
                cout << endl << "*************第 " << ++ j << " 次读写操作完成,开始读文件 ***************"<<endl;
                ReadFile(hSrcFile, lpAddr, sizeMIN, NULL, &ovlpRead); 
                 
            } //else if 


        } //while


        SetFilePointerEx(hDestFile, liFileSize, NULL, FILE_BEGIN);
        SetEndOfFile(hDestFile);


        cout << endl << " $$$$$$$$$$$$$$$$$$$$$ 操作完成 $$$$$$$$$$$$$$$$$" <<endl; 
         
    }
    __finally
    {
        cout << endl << "清理资源" <<endl;
        if (INVALID_HANDLE_VALUE != hSrcFile)
            CloseHandle(hSrcFile);
        hSrcFile = INVALID_HANDLE_VALUE;


        if(INVALID_HANDLE_VALUE != hDestFile)
            CloseHandle(hDestFile);
        hDestFile = INVALID_HANDLE_VALUE;


        if(NULL != lpAddr)
            VirtualFree(lpAddr, 0, MEM_RELEASE | MEM_DECOMMIT);
        lpAddr = NULL; 
    }
    




    cout << endl << endl;
    return 0;
}








void ShowErrMsg(LPCSTR lpMsg){    cout << endl << "Some error happened : " << lpMsg << "\n"; }

版权声明:本文为博主原创文章,未经博主允许不得转载。

 

转载于:https://www.cnblogs.com/qq76211822/p/4712074.html

<template> <view class="chat-container"> <!-- 消息列表区域 --> <view class="message-list" ref="messageList"> <view v-for="(message, index) in messages" :key="index" :class="['message', message.isUser ? 'user-message' : 'system-message']"> <!-- 用户消息 --> <view v-if="message.isUser" class="message-content"> <view class="avatar user-avatar">👤</view> <view class="bubble"> <p>{{ message.content }}</p> <view v-if="message.taskId" class="task-info"> <span class="tag">{{ message.type === 'image' ? '图片生成' : '视频生成' }}</span> <span class="status" :class="message.status">{{ getStatusText(message.status) }}</span> </view> </view> </view> <!-- 系统消息 --> <view v-else class="message-content"> <view class="avatar system-avatar">🤖</view> <view class="bubble"> <!-- 生成状态 --> <view v-if="message.status === 'pending'" class="generating"> <view class="loading-spinner"></view> <p>正在生成{{ message.type === 'image' ? '图片' : '视频' }},请稍候...</p> </view> <!-- 生成结果 --> <view v-if="message.status === 'completed'"> <view v-if="message.type === 'image'"> <image style="width: 50rpx; height: 50rpx;" :src="message.url" alt="生成的图片" @click="previewImage(message.url)" /> <p class="hint">点击图片查看大图</p> </view> <view v-else-if="message.type === 'video'"> <video controls :src="message.url"></video> <p class="hint">视频生成完成</p> </view> </view> <!-- 错误提示 --> <view v-if="message.status === 'error'" class="error-message"> <p>⚠️ 生成失败: {{ message.error }}</p> </view> </view> </view> </view> </view> <!-- 输入区域 --> <view class="input-area"> <textarea v-model="inputText" placeholder="输入描述文字..." @keyup.enter="sendMessage"></textarea> <view class="action-buttons"> <button @click="generateImage" :disabled="!inputText.trim()">生成图片</button> <button @click="generateVideo" :disabled="!inputText.trim()">生成视频</button> </view> </view> <!-- 任务队列悬浮窗 --> <view class="task-queue" v-if="taskQueue.length > 0"> <h4>生成队列 ({{ processingTask ? '处理中' : '等待中' }})</h4> <ul> <li v-for="(task, index) in taskQueue" :key="task.id" :class="['task-item', index === 0 && processingTask ? 'processing' : '']"> <span class="task-type">{{ task.type === 'image' ? '🖼️' : '🎬' }}</span> <span class="task-prompt">{{ task.prompt }}</span> <span class="task-status">{{ getQueueStatus(index) }}</span> </li> </ul> </view> </view> </template> <script> export default { data() { return { inputText: '', messages: [], taskQueue: [], processingTask: null, nextTaskId: 1 }; }, mounted() { // 添加初始欢迎消息 this.addSystemMessage('欢迎使用AI生成助手!请描述您想要生成的图片或视频内容。'); }, methods: { // 添加用户消息 addUserMessage(content, type) { this.messages.push({ id: Date.now(), isUser: true, content, type, status: 'queued', taskId: this.nextTaskId++ }); this.scrollToBottom(); }, // 添加系统消息 addSystemMessage(content, type = 'text', status = 'completed') { this.messages.push({ id: Date.now(), isUser: false, content, type, status }); this.scrollToBottom(); }, // 滚动到底部 scrollToBottom() { this.$nextTick(() => { const container = this.$refs.messageList; container.scrollTop = container.scrollHeight; }); }, // 生成图片 generateImage() { if (!this.inputText.trim()) return; const prompt = this.inputText.trim(); this.inputText = ''; // 添加用户消息 this.addUserMessage(prompt, 'image'); // 添加到任务队列 this.addToQueue({ type: 'image', prompt, taskId: this.nextTaskId - 1 }); }, // 生成视频 generateVideo() { if (!this.inputText.trim()) return; const prompt = this.inputText.trim(); this.inputText = ''; // 添加用户消息 this.addUserMessage(prompt, 'video'); // 添加到任务队列 this.addToQueue({ type: 'video', prompt, taskId: this.nextTaskId - 1 }); }, // 添加到任务队列 addToQueue(task) { this.taskQueue.push(task); // 添加系统提示消息 this.addSystemMessage(`您的${task.type === 'image' ? '图片' : '视频'}生成任务已加入队列`, 'text'); // 如果没有正在处理的任务,开始处理 if (!this.processingTask) { this.processQueue(); } }, // 处理任务队列 async processQueue() { if (this.taskQueue.length === 0) { this.processingTask = null; return; } // 获取第一个任务 this.processingTask = this.taskQueue[0]; // 更新消息状态为处理中 this.updateMessageStatus(this.processingTask.taskId, 'pending'); try { // 模拟生成过程(实际应调用API) const result = await this.generateContent(this.processingTask); // 添加系统结果消息 this.addSystemMessage(result.url, this.processingTask.type, 'completed'); // 更新消息状态为完成 this.updateMessageStatus(this.processingTask.taskId, 'completed'); // 从队列中移除已完成任务 this.taskQueue.shift(); // 处理下一个任务 this.processQueue(); } catch (error) { // 添加错误消息 this.addSystemMessage(`生成失败: ${error.message}`, 'text', 'error'); // 更新消息状态为错误 this.updateMessageStatus(this.processingTask.taskId, 'error', error.message); // 从队列中移除失败任务 this.taskQueue.shift(); // 处理下一个任务 this.processQueue(); } }, // 更新消息状态 updateMessageStatus(taskId, status, error = '') { const message = this.messages.find(m => m.taskId === taskId); if (message) { message.status = status; if (error) message.error = error; } }, // 生成内容(模拟) generateContent(task) { return new Promise((resolve, reject) => { // 模拟API调用延迟 setTimeout(() => { if (Math.random() > 0.1) { // 90%成功率 resolve({ url: task.type === 'image' ? `https://picsum.photos/400/300?random=${Math.floor(Math.random() * 1000)}` : 'https://sample-videos.com/video123/mp4/720/big_buck_bunny_720p_1mb.mp4' }); } else { reject(new Error('AI生成服务暂时不可用')); } }, task.type === 'image' ? 3000 : 6000); // 图片3秒,视频6秒 }); }, // 预览图片 previewImage(url) { // 实际项目中应使用图片预览组件 window.open(url, '_blank'); }, // 获取状态文本 getStatusText(status) { const statusMap = { queued: '队列中', pending: '生成中', completed: '已完成', error: '失败' }; return statusMap[status] || status; }, // 获取队列状态 getQueueStatus(index) { if (index === 0 && this.processingTask) return '处理中'; return `等待 ${index}`; } } }; </script> <style scoped> .chat-container { display: flex; flex-direction: column; height: 100vh; max-width: 800px; margin: 0 auto; background-color: #f0f2f5; position: relative; } .message-list { flex: 1; overflow-y: auto; padding: 20px; display: flex; flex-direction: column; gap: 15px; } .message-content { display: flex; max-width: 80%; } .user-message .message-content { margin-left: auto; flex-direction: row-reverse; } .system-message .message-content { margin-right: auto; } .avatar { width: 40px; height: 40px; border-radius: 50%; display: flex; align-items: center; justify-content: center; font-size: 20px; flex-shrink: 0; margin: 0 10px; } .user-avatar { background-color: #1890ff; color: white; } .system-avatar { background-color: #52c41a; color: white; } .bubble { padding: 12px 15px; border-radius: 18px; position: relative; max-width: 100%; word-break: break-word; } .user-message .bubble { background-color: #1890ff; color: white; border-bottom-right-radius: 5px; } .system-message .bubble { background-color: white; color: #333; border-bottom-left-radius: 5px; box-shadow: 0 1px 2px rgba(0, 0, 0, 0.1); } .task-info { margin-top: 8px; font-size: 0.8em; opacity: 0.8; display: flex; align-items: center; gap: 8px; } .tag { background: rgba(255, 255, 255, 0.2); padding: 2px 6px; border-radius: 4px; } .status { padding: 2px 6px; border-radius: 4px; } .status.queued { background-color: #f0f0f0; color: #666; } .status.pending { background-color: #e6f7ff; color: #1890ff; } .status.completed { background-color: #f6ffed; color: #52c41a; } .status.error { background-color: #fff2f0; color: #ff4d4f; } .generating { display: flex; align-items: center; gap: 10px; } .loading-spinner { width: 20px; height: 20px; border: 3px solid rgba(0, 0, 0, 0.1); border-top-color: #1890ff; border-radius: 50%; animation: spin 1s linear infinite; } @keyframes spin { to { transform: rotate(360deg); } } .input-area { padding: 15px; background-color: white; border-top: 1px solid #e8e8e8; border-radius: 15px; } textarea { width: 95%; min-height: 60px; padding: 10px; border: 1px solid #d9d9d9; border-radius: 4px; resize: none; font-family: inherit; border-radius: 15px; } .action-buttons { display: flex; gap: 10px; margin-top: 10px; } button { flex: 1; /* padding: 10px; */ background-color: #1890ff; color: white; border: none; border-radius: 4px; cursor: pointer; transition: background-color 0.3s; } button:disabled { background-color: #bfbfbf; cursor: not-allowed; } button:hover:not(:disabled) { background-color: #40a9ff; } .task-queue { position: absolute; top: 80rpx; right: 20px; background: white; border-radius: 8px; box-shadow: 0 2px 8px rgba(0, 0, 0, 0.15); padding: 15px; max-width: 300px; z-index: 100; } .task-queue h4 { margin-top: 0; margin-bottom: 10px; color: #333; } .task-item { padding: 8px 0; border-bottom: 1px solid #f0f0f0; display: flex; align-items: center; gap: 10px; } .task-item:last-child { border-bottom: none; } .task-type { font-size: 1.2em; } .task-prompt { flex: 1; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; } .task-status { font-size: 0.85em; color: #666; } .task-item.processing .task-status { color: #1890ff; font-weight: bold; } image, video { max-width: 100%; border-radius: 8px; display: block; margin-top: 5px; } video { max-width: 400px; } .hint { font-size: 0.8em; color: #666; margin-top: 5px; } .error-message { color: #ff4d4f; } </style> 你看看 为什么系统消息有一个空的气泡 就是我点击生成图片之后生成成功就会出现一个 开始没有发消息也出现了一个 解决一下
最新发布
08-05
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值