Cara membatalkan kerja saluran berdasarkan ID dalam golang

PHPz
Lepaskan: 2024-02-08 23:42:11
ke hadapan
715 orang telah melayarinya

Cara membatalkan kerja saluran berdasarkan ID dalam golang

Di golang, membatalkan kerja saluran adalah keperluan biasa. Apabila kita berurusan dengan tugasan serentak, kadangkala kita perlu membatalkan tugas pelaksanaan berdasarkan ID tugas. Jadi, bagaimana untuk melaksanakan fungsi ini dalam golang? Di bawah, saya akan memperkenalkan anda kepada kaedah yang mudah dan berkesan. Pertama, kita perlu mencipta saluran penimbal untuk menyimpan ID tugasan. Kami kemudiannya boleh menggunakan pernyataan pilih untuk mendengar operasi bacaan saluran dan menghantar ID tugasan ke saluran apabila tugasan perlu dibatalkan. Kemudian, dalam fungsi pelaksanaan tugas, kita boleh menentukan sama ada tugas itu perlu dibatalkan dengan menilai sama ada saluran ditutup. Jika saluran ditutup, tugas itu telah dibatalkan dan kami boleh menamatkan pelaksanaan tugas di tempat yang sesuai. Dengan cara ini, kami boleh membatalkan kerja saluran dengan mudah berdasarkan ID dalam golang. Di atas adalah kaedah yang diperkenalkan oleh editor php Xinyi, saya harap ia akan membantu semua orang!

Kandungan soalan

Jadi saya ada satu post 端点,它创建一个作业并将它们添加到一个 chan 中。 workerjobschan = make(chan job, maxqueuesize)

Beginilah saya melakukan tugas saya di saluran (main.go):

for i := 1; i <= maxworkers; i++ {
    go func(i int) {
        for job := range workerjobschan {
            ctx, cancel := context.withcancel(context.background())
            storejob(job.search.id, cancel)
            job.execute(ctx, c.db, i)
        }
    }(i)
}
Salin selepas log masuk

Saya menyimpan fungsi pembatalan dalam peta: canceljobfuncs = make(map[int]context.cancelfunc).

Ini adalah fungsi kerja:

func (j *job) execute(ctx context.context, db *sql.db, workerid int) error {


    for {
        select {
        // check for cancellation signal
        case <-ctx.done():
             if err := ctx.err(); err != nil {
                fmt.println("worker", workerid, "error", err)
             }
            fmt.println("worker", workerid, "cancelled")
            return nil

        default:
            fmt.printf("worker%d: processing %s\n", workerid, j.search.query)
            time.sleep(2 * time.second)
            fmt.printf("worker%d: active %s\n", workerid, j.search.query)
            time.sleep(5 * time.second)
            fmt.printf("worker%d: completed %s!\n", workerid, j.search.query)

        }
    }
}
Salin selepas log masuk

Saya membatalkan konteks (dalam pengendali http) seperti ini:

cancelJob(search.ID)
Salin selepas log masuk

Tetapi kerja tetap berjalan. Saya telah mencuba banyak perkara tetapi nampaknya tidak berjaya.

Penyelesaian

Berikut ialah cara untuk menggambarkan perkara yang jelas: jika kod anda tidak menyemak ctx.done(), ia tidak mempunyai cara untuk mengetahui bahawa ia telah dibatalkan.
(BTW, ini adalah satu lagi parafrasa tentang apa yang @jimb tulis dalam ulasan untuk soalan anda).

Jadi apabila kod dalam kaedah .execute(...) mula melaksanakan blok ini:

fmt.printf("worker%d: processing %s\n", workerid, j.search.query)
    time.sleep(2 * time.second)
    fmt.printf("worker%d: active %s\n", workerid, j.search.query)
    time.sleep(5 * time.second)
    fmt.printf("worker%d: completed %s!\n", workerid, j.search.query)
Salin selepas log masuk

Ia akan sampai ke penghujung blok (7 saat). Tiada arahan yang menyuruhnya berhenti pada pembatalan.

Jika anda mahu fungsi anda dapat mengesan pembatalan semasa arahan "tidur", anda perlu menukar kod anda.

Berikut ialah contoh cara melakukan ini menggunakan contoh anda:

func (j *job) execute(ctx context.context, db *sql.db, workerid int) error {


    for {
        fmt.printf("worker%d: processing %s\n", workerid, j.search.query)

        // rewrite time.sleep() with time.after() so that it can be composed
        // in a select statement:
        select {
        case <-ctx.done():
            fmt.println("worker", workerid, "cancelled")
            return nil
        case <-time.after(2 * time.second):
            // keep going
        }

        fmt.printf("worker%d: active %s\n", workerid, j.search.query)

        select {
        case <-ctx.done():
            fmt.println("worker", workerid, "cancelled")
            return nil
        case <-time.after(5 * time.second):
            // keep going
        }

        fmt.printf("worker%d: completed %s!\n", workerid, j.search.query)
    }
}
Salin selepas log masuk

https://www.php.cn/link/3bc31a430954d8326605fc690ed22f4d

Saya rasa kod sebenar anda tidak mempunyai time.sleep() 指令,而是 processsearch(...)doquery(...) atau ...

Jika anda memerlukan fungsi ini boleh dibatalkan semasa pelaksanaan, anda perlu menyerahkan konteks pembatalan kepada mereka entah bagaimana dan minta mereka menyemak pembatalan dalam beberapa cara.

Salah satu cara untuk "lulus konteks" jelas sekali dengan menambahkannya pada parameter fungsi tersebut:

processsearch(ctx, ...)
doquery(ctx, ...)
Salin selepas log masuk

Tetapi bergantung pada kod sedia ada anda, sesetengah parameter mungkin sudah mempunyai kaedah terbina dalam untuk membatalkan.
Contohnya:

// an http.Request carries a context:
func doQuery(req *http.Request, ....) {
    ...
}

// at call site:
    ...
    req := http.NewRequestWithContext(ctx, "GET", "https://some.other.service/", nil)
    doQuery(req, ...)
Salin selepas log masuk

Atas ialah kandungan terperinci Cara membatalkan kerja saluran berdasarkan ID dalam golang. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!

sumber:stackoverflow.com
Kenyataan Laman Web ini
Kandungan artikel ini disumbangkan secara sukarela oleh netizen, dan hak cipta adalah milik pengarang asal. Laman web ini tidak memikul tanggungjawab undang-undang yang sepadan. Jika anda menemui sebarang kandungan yang disyaki plagiarisme atau pelanggaran, sila hubungi admin@php.cn
Tutorial Popular
Lagi>
Muat turun terkini
Lagi>
kesan web
Kod sumber laman web
Bahan laman web
Templat hujung hadapan
Tentang kita Penafian Sitemap
Laman web PHP Cina:Latihan PHP dalam talian kebajikan awam,Bantu pelajar PHP berkembang dengan cepat!