登录
首页 >  Golang >  Go问答

以共享库的形式实现函数异步返回进度

来源:stackoverflow

时间:2024-03-05 09:30:26 299浏览 收藏

知识点掌握了,还需要不断练习才能熟练运用。下面golang学习网给大家带来一个Golang开发实战,手把手教大家学习《以共享库的形式实现函数异步返回进度》,在实现功能的过程中也带大家重新温习相关知识点,温故而知新,回头看看说不定又有不一样的感悟!

问题内容

所以我想使用下面的方法创建一个在 golang 中下载文件的函数,我使用

将这个 golang 项目构建到 c .dll 中
go build -buildmode=c-shared -o patcher.dll main.go

我设法在我的 c# 应用程序上使用此函数来获取文件下载进度,如果我只是使用 downloadfile() 直接打印它,我当前的函数 (downloadffile) 就可以工作,但是我想在我的 c# 应用程序上异步获取进度,但我无法直接获取该值,所以我认为我需要从我的 golang 应用程序返回整数进度,但如果我这样做,该函数只会执行 1 次(进度的最后结果)

问题是如何让我的 go func downloadfile 在我的 c# 应用程序上被调用 1 次,但我仍然可以跟踪进度? 任何帮助将不胜感激,谢谢。

func DownloadFile(){
    // create client
    client := grab.NewClient()
    req, _ := grab.NewRequest(".", "http://www.golang-book.com/public/pdf/gobook.pdf")

    // start download
    fmt.Printf("Downloading %v...\n", req.URL())
    resp := client.Do(req)
    fmt.Printf("  %v\n", resp.HTTPResponse.Status)

    // start UI loop
    t := time.NewTicker(500 * time.Millisecond)
    defer t.Stop()

Loop:
    for {
        select {
        case <-t.C:
            fmt.Printf("%.2f%",
                //resp.BytesComplete(),
                //resp.Size,
                100*resp.Progress())

        case <-resp.Done:
            // download is complete
            break Loop
        }
    }

    // check for errors
    if err := resp.Err(); err != nil {
        fmt.Fprintf(os.Stderr, "Download failed: %v\n", err)
        os.Exit(1)
    }

    // fmt.Printf("Download saved to ./%v \n", resp.Filename)

    // Output:
    // Downloading http://www.golang-book.com/public/pdf/gobook.pdf...
    //   200 OK
    //   transferred 42970 / 2893557 bytes (1.49%)
    //   transferred 1207474 / 2893557 bytes (41.73%)
    //   transferred 2758210 / 2893557 bytes (95.32%)
    // Download saved to ./gobook.pdf
}

解决方案


所以,在谷歌搜索后,我找到了答案,我需要在 go 上让 setter 和 getter “a like”,如下所示。

var progress int
var downloadspeed int

//export downloadfile
func downloadfile(){
    // create client
    client := grab.newclient()
    req, _ := grab.newrequest(".", "https://upload.wikimedia.org/wikipedia/commons/d/d6/wp-w4-big.jpg")

    // start download
    fmt.printf("downloading %v...\n", req.url())
    resp := client.do(req)
    fmt.printf("  %v\n", resp.httpresponse.status)

    // start ui loop
    t := time.newticker(500 * time.millisecond)
    defer t.stop()

loop:
    for {
        select {
        case <-t.c:

            //progress = 100*(resp.progress())

            setprogressvalue(int(resp.progress() * 100))
            setdownloadspeedvalue(int(resp.bytespersecond()))
            //fmt.println(progress)
        case <-resp.done:
            // download is complete
            setprogressvalue(100)
            //fmt.println(progress)
            break loop
        }
    }

    // check for errors
    if err := resp.err(); err != nil {
        fmt.fprintf(os.stderr, "download failed: %v\n", err)
        os.exit(1)
    }

    fmt.printf("download saved to ./%v \n", resp.filename)
    fmt.println("completed")
}

//export progressvalue
func progressvalue() int {
    return progress
}

//export setprogressvalue
func setprogressvalue(val int) {
    progress = val
}

然后在c#中使用:

void worker_DoWork(object sender, DoWorkEventArgs e) {
    [DllImport(@"M:\GolangProjects\PatcherDLL\patcher.dll", EntryPoint = "ProgressValue")]
     static extern int ProgressValue();

    public partial class MainWindow : Window {
    var task = Task.Factory.StartNew(() => {
                    DownloadFile();
                });

                while (!task.IsCompleted)
                {
                    Thread.Sleep(100);

                    string downloadSpeedFormatted = "";

                    if (DownloadSpeedValue()/1000 > 999)
                    {
                        downloadSpeedFormatted = Math.Round((double) DownloadSpeedValue() / 1000000, 2) + " MB/s";
                    } else
                    {
                        downloadSpeedFormatted = DownloadSpeedValue() / 1000 + " kb/s";
                    }

                    Dispatcher.BeginInvoke(new Action(delegate {
                        progressbar1.Value = ProgressValue();
                        progressPercent1.Text = ProgressValue() + "%";
                        downloadSpeeds.Content = downloadSpeedFormatted;
                    }));
                }
    }
}

到这里,我们也就讲完了《以共享库的形式实现函数异步返回进度》的内容了。个人认为,基础知识的学习和巩固,是为了更好的将其运用到项目中,欢迎关注golang学习网公众号,带你了解更多关于的知识点!

声明:本文转载于:stackoverflow 如有侵犯,请联系study_golang@163.com删除
相关阅读
更多>
最新阅读
更多>
课程推荐
更多>