코 루틴으로 파일 읽기 및 복사

무리 요 코 미노

몇 가지 의심을 설명하기 위해 다음 응용 프로그램을 만들었습니다. Github의 내 예

이 예에서는 파일을 다른 패키지에 복사합니다.

내 의심은 다음과 같습니다.

  1. 작업을 병렬로 수행하면 취소 전에 완료된 값을 반환 할 수 있습니까?

  2. contentResolver.openInputStream (uri)IO 컨텍스트로 작업하는 동안 "Inappropriate blocking method call"메시지가 나타나는 이유는 무엇 입니까?

  3. 출력에 복사 할 파일 항목을 읽는 동안 항상 작업 상태를 확인하여이 작업이 취소되면 즉시 중지되고 생성 된 출력 파일이 삭제되고 취소 예외를 반환합니다. 맞습니까?

  4. 수행되는 작업의 양을 구분할 수 있습니까?

내 onCreate :

private val listUri = mutableListOf<Uri>()
private val job = Job()

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    setContentView(R.layout.activity_main)
    
    //get files from 1 to 40
    val packageName = "android.resource://${packageName}/raw/"
    for (i in 1..40) {
        listUri.add(Uri.parse("${packageName}file$i"))
    }
}

내 버튼 동작 :

  //Button action
   fun onClickStartTask(view: View) {
        var listNewPath = emptyList<String>()
        CoroutineScope(Main + job).launch {
            try {
                //shows something in the UI - progressBar
                withContext(IO) {
                    listNewPath = listUri.map { uri ->
                        async {
                            //path to file temp
                            val pathFileTemp =
                                "${getExternalFilesDir("Temp").toString()}/${uri.lastPathSegment}"
                            val file = File(pathFileTemp)
                            val inputStream = contentResolver.openInputStream(uri)
                            inputStream?.use { input ->
                                FileOutputStream(file).use { output ->
                                    val buffer = ByteArray(1024)
                                    var read: Int = input.read(buffer)
                                    while (read != -1) {
                                        if (isActive) {
                                            output.write(buffer, 0, read)
                                            read = input.read(buffer)
                                        } else {
                                            input.close()
                                            output.close()
                                            file.deleteRecursively()
                                            throw CancellationException()
                                        }
                                    }
                                }
                            }
                            //If completed then it returns the new path.
                            return@async pathFileTemp
                        }
                    }.awaitAll()
                }
            } finally {
                //shows list complete in the UI
            }
        }
    }

작업 취소 버튼 :

fun onClickCancelTask(view: View) {
    if (job.isActive) {
        job.cancelChildren()
        println("Cancel children")
    }
}

이것은 작업을 수행하는 버튼 동작입니다.

모든 도움에 감사드립니다.

서커스 매그너스

답변 1. 및 4 .:

병렬 작업을 구분하고 독립적으로 완료되도록하려면 (일부 값을 가져오고 나머지는 취소) 채널을 사용해야하며 가급적 흐름을 사용해야합니다. 단순화 된 예 :

fun processListWithSomeWorkers(list: List<Whatever>, concurrency: Int): Flow<Result> = channelFlow {
   val workToDistribute = Channel<Whatever>()
   launch { for(item in list) workToDistribute.send(item) } // one coroutine distributes work...

    repeat(concurrency) { // launch a specified number of worker coroutines
      launch { 
         for (task in workToDistribute) { // which process tasks in a loop
            val atomicResult = process(task)
            send(atomicResult) // and send results downstream to a Flow
         }
      }
   }
}

그런 다음 전체 흐름이 완료 될 때까지 기다리는 결과가 생성 될 때 하나씩 처리 할 수 ​​있습니다. 예를 들어 원하는 경우 일부만 가져 resultFlow.take(20).onEach { ... }.collectIn(someScope)옵니다. 흐름이기 때문에 누군가 수집을 시작할 때만 작동하기 시작합니다 ( 그것은 일반적으로 좋은 것입니다.

좀 더 구체적이고 실험적인 기능 (프로덕션)을 발견 할 수 있으므로 전체를 조금 더 짧게 만들 수 있습니다. 다음과 같이 Flow 연산자로 일반화 할 수 있습니다.

fun <T, R> Flow<T>.concurrentMap(concurrency: Int, transform: suspend (T) -> R): Flow<R> {
    require(concurrency > 1) { "No sense with concurrency < 2" }
    return channelFlow {
        val inputChannel = produceIn(this)
        repeat(concurrency) {
            launch {
                for (input in inputChannel) send(transform(input))
            }
        }
    }
}

사용 : list.asFlow().concurrentMap(concurrency = 4) { <your mapping logic> }

corotuines 팀은 병렬 연산자 제품군을 Flow 스트림에 추가하려고 생각하고 있지만 아직 AFAIK가 없습니다.

이 기사는 인터넷에서 수집됩니다. 재 인쇄 할 때 출처를 알려주십시오.

침해가 발생한 경우 연락 주시기 바랍니다[email protected] 삭제

에서 수정
0

몇 마디 만하겠습니다

0리뷰
로그인참여 후 검토

관련 기사

분류에서Dev

루비 코드로 YAML 파일 읽기 및 업데이트

분류에서Dev

filestream 및 streamreader를 사용하여 C #으로 파일 읽기

분류에서Dev

파일에서 세트 읽기 및 키 사전으로 변경

분류에서Dev

파일 복사 및 파일 정보를 거꾸로 쓰기

분류에서Dev

txt 파일로 필터링 된 파일 찾기 및 복사

분류에서Dev

Python으로 파일 읽기 및 인쇄

분류에서Dev

unix alias 명령으로 파일 복사 및 덮어 쓰기

분류에서Dev

코 루틴을 사용하여 로그의 순서를 잃지 않고 로그 파일에 쓰기

분류에서Dev

POST를 통해 PHP 파일로 매개 변수 보내기 및 PHP 파일의 에코 읽기

분류에서Dev

파일 읽기 및 사전과 비교

분류에서Dev

파일 읽기 및 사전과 비교

분류에서Dev

파일 읽기 및 사전 확인

분류에서Dev

코 루틴, 비동기 DiffUtil 및 불일치 감지 오류

분류에서Dev

여러 행으로 변수 및 데이터 레코드가있는 PHP에서 텍스트 파일 읽기

분류에서Dev

Cython 및 Pandas로 TXT 파일 읽기

분류에서Dev

상대 경로가있는 파일 찾기 및 복사

분류에서Dev

GNU 병렬로 파일 복사 및 이름 바꾸기

분류에서Dev

txt 파일을 사전으로 읽기

분류에서Dev

파일 시스템을 사용하지 않고 일시적으로 데이터 읽기 및 쓰기

분류에서Dev

중첩 루프를 사용하여 파일 읽기 및 비교 문제

분류에서Dev

파일을 복사하기 위해 일치하는 폴더 및 파일 이름 패턴으로 rsync

분류에서Dev

파일 복사 및 이름 바꾸기

분류에서Dev

PySpark : newAPIHadoopFile을 사용하여 여러 줄 레코드 텍스트 파일에서 읽기, 매핑 및 축소

분류에서Dev

ExtAudioFileSeek 및 ExtAudioFileRead를 사용하여 오디오 파일에서 인코딩 된 프레임 읽기

분류에서Dev

파일에서 읽기 및 명령 줄을 통해 내용 복사

분류에서Dev

C / STM32-.wav 파일에서 데이터 읽기 및 복사

분류에서Dev

읽기 파일, 쓰기 파일 및 배열을 사용하는 Java 프로젝트

분류에서Dev

Python으로 .docx 파일 읽기 및 쓰기

분류에서Dev

C #으로 .PLY 파일 읽기 및 가져 오기

Related 관련 기사

  1. 1

    루비 코드로 YAML 파일 읽기 및 업데이트

  2. 2

    filestream 및 streamreader를 사용하여 C #으로 파일 읽기

  3. 3

    파일에서 세트 읽기 및 키 사전으로 변경

  4. 4

    파일 복사 및 파일 정보를 거꾸로 쓰기

  5. 5

    txt 파일로 필터링 된 파일 찾기 및 복사

  6. 6

    Python으로 파일 읽기 및 인쇄

  7. 7

    unix alias 명령으로 파일 복사 및 덮어 쓰기

  8. 8

    코 루틴을 사용하여 로그의 순서를 잃지 않고 로그 파일에 쓰기

  9. 9

    POST를 통해 PHP 파일로 매개 변수 보내기 및 PHP 파일의 에코 읽기

  10. 10

    파일 읽기 및 사전과 비교

  11. 11

    파일 읽기 및 사전과 비교

  12. 12

    파일 읽기 및 사전 확인

  13. 13

    코 루틴, 비동기 DiffUtil 및 불일치 감지 오류

  14. 14

    여러 행으로 변수 및 데이터 레코드가있는 PHP에서 텍스트 파일 읽기

  15. 15

    Cython 및 Pandas로 TXT 파일 읽기

  16. 16

    상대 경로가있는 파일 찾기 및 복사

  17. 17

    GNU 병렬로 파일 복사 및 이름 바꾸기

  18. 18

    txt 파일을 사전으로 읽기

  19. 19

    파일 시스템을 사용하지 않고 일시적으로 데이터 읽기 및 쓰기

  20. 20

    중첩 루프를 사용하여 파일 읽기 및 비교 문제

  21. 21

    파일을 복사하기 위해 일치하는 폴더 및 파일 이름 패턴으로 rsync

  22. 22

    파일 복사 및 이름 바꾸기

  23. 23

    PySpark : newAPIHadoopFile을 사용하여 여러 줄 레코드 텍스트 파일에서 읽기, 매핑 및 축소

  24. 24

    ExtAudioFileSeek 및 ExtAudioFileRead를 사용하여 오디오 파일에서 인코딩 된 프레임 읽기

  25. 25

    파일에서 읽기 및 명령 줄을 통해 내용 복사

  26. 26

    C / STM32-.wav 파일에서 데이터 읽기 및 복사

  27. 27

    읽기 파일, 쓰기 파일 및 배열을 사용하는 Java 프로젝트

  28. 28

    Python으로 .docx 파일 읽기 및 쓰기

  29. 29

    C #으로 .PLY 파일 읽기 및 가져 오기

뜨겁다태그

보관