You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何使用mpb库创建两行式进度条及多进度条实时更新?

用mpb实现两行式多进度条

核心实现思路

利用mpb的自定义装饰器,为每个进度条绑定动态更新的状态行(单独占一行),下方紧跟进度条。通过线程安全的状态结构体管理任务信息,搭配高刷新率配置实现实时更新。

完整代码示例

package main

import (
	"fmt"
	"path/filepath"
	"sync"
	"time"

	"github.com/vbauerster/mpb/v8"
	"github.com/vbauerster/mpb/v8/decor"
)

// TaskStatus 管理单个任务的状态信息,保证线程安全
type TaskStatus struct {
	mu       sync.Mutex
	filename string
	mode     string
	pass     string
	done     bool
}

// String 返回格式化后的状态行文本
func (ts *TaskStatus) String() string {
	ts.mu.Lock()
	defer ts.mu.Unlock()

	var status string
	if ts.done {
		status = fmt.Sprintf("Processing DONE [Mode: %s]", ts.mode)
	} else {
		status = fmt.Sprintf("Processing %s ...", ts.filename)
		if ts.mode != "" {
			status += fmt.Sprintf(" [Mode: %s]", ts.mode)
		}
		if ts.pass != "" {
			status += fmt.Sprintf(" [Pass: %s]", ts.pass)
		}
	}
	return status
}

// Update 更新任务状态
func (ts *TaskStatus) Update(filename, mode, pass string, done bool) {
	ts.mu.Lock()
	defer ts.mu.Unlock()
	ts.filename = filename
	ts.mode = mode
	ts.pass = pass
	ts.done = done
}

func main() {
	// 待处理文件列表
	list := []string{
		"C:\\Temp\\01.png",
		"C:\\Temp\\02.png",
		"C:\\Temp\\03.png",
		"C:\\Temp\\test.png",
		"C:\\Temp\\test01.png",
	}
	totalTasks := len(list)

	// 初始化mpb,设置高刷新率保证实时更新
	p := mpb.New(mpb.WithRefreshRate(10 * time.Millisecond))

	var wg sync.WaitGroup
	wg.Add(totalTasks)

	for idx, filePath := range list {
		filename := filepath.Base(filePath)
		status := &TaskStatus{}
		// 初始状态:处理当前文件,模式WebP
		status.Update(filename, "WebP", "", false)

		// 创建进度条:总步数为任务总数,每行分为状态行+进度条
		bar := p.AddBar(int64(totalTasks),
			mpb.PrependDecorators(
				// 自定义装饰器:输出状态行并换行
				decor.Func(func(s decor.Statistics) string {
					return status.String() + "\n"
				}),
				// 进度计数:当前完成数/总任务数
				decor.CountersNoUnit("%d / %d", decor.WCSyncWidth),
			),
			mpb.AppendDecorators(
				// 进度条样式
				decor.Percentage(decor.WCSyncWidth),
				decor.ETA(decor.ET_STYLE_GO),
			),
			// 设置进度条宽度
			mpb.BarWidth(25),
		)

		// 模拟任务处理协程
		go func(taskIdx int, b *mpb.Bar, ts *TaskStatus) {
			defer wg.Done()

			// 模拟第一次处理耗时
			time.Sleep(1500 * time.Millisecond)
			// 完成一个任务,进度+1
			b.Increment()

			// 模拟重复处理同一文件(仅第一个任务)
			if taskIdx == 0 {
				// 更新状态:切换为WebM模式,第一次pass
				ts.Update("01.mp4", "WebM", "1/2", false)
				time.Sleep(1500 * time.Millisecond)
				// 更新状态:第二次pass,进度保持不变
				ts.Update("01.mp4", "WebM", "2/2", false)
				time.Sleep(1500 * time.Millisecond)
			}

			// 标记任务完成
			ts.Update(filename, "WebP", "", true)
			// 等待状态刷新后结束
			time.Sleep(100 * time.Millisecond)
		}(idx, bar, status)
	}

	// 等待所有任务完成
	wg.Wait()
	// 等待mpb输出结束
	p.Wait()
}

关键特性说明

  • 动态状态行:通过TaskStatus结构体管理任务信息,自定义装饰器实时渲染状态行,支持添加模式、处理次数等额外信息。
  • 重复处理无进度变化:重复处理同一文件时,仅更新状态文本,不调用Increment(),进度条保持当前进度。
  • 实时多进度条:设置WithRefreshRate(10*time.Millisecond)保证状态变化后立即刷新,多个进度条独立更新互不干扰。
  • 线程安全:TaskStatus使用互斥锁保证多协程下的状态更新安全。

内容的提问来源于stack exchange,提问作者tetratheta

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.22 02:50:42