none
비동기에 수동으로 데이터를 넣는데 익셉션이 발생합니다. 원인을 모르겠네요....ㅜㅜ RRS feed

  • 질문

  • void Dailibrary::DayViewPage::SetBindableDataClick(Platform::Object^ sender, Windows::UI::Xaml::RoutedEventArgs^ e)
    {
    	makeCalendar();
    }
    
    
    void Dailibrary::DayViewPage::makeCalendar()
    {
    	vector<vector<wstring>> exyears = db->query(L"select year from cyear order by year desc;");
    	vector<wstring> rows;
    	Calendar ^ dal;
    	String ^ dayofweek;
    	TextBlock ^ forprintday;
    	int week = 0;
    	int daycounter = 0;
    	int day = 1;
    
    	Grid ^ calendarcontainer;
    	Windows::UI::Xaml::Shapes::Rectangle ^ rec;
    
    	for(vector<vector<wstring>>::iterator it = exyears.begin();it < exyears.end(); it++)
    	{
    		rows = *it;
    		calendarcontainer = ref new Grid();
    		week = 0;
    		
    
    		calendarcontainer->ColumnDefinitions->Append(ref new Windows::UI::Xaml::Controls::ColumnDefinition());
    		calendarcontainer->ColumnDefinitions->Append(ref new Windows::UI::Xaml::Controls::ColumnDefinition());
    		calendarcontainer->ColumnDefinitions->Append(ref new Windows::UI::Xaml::Controls::ColumnDefinition());
    		calendarcontainer->ColumnDefinitions->Append(ref new Windows::UI::Xaml::Controls::ColumnDefinition());
    		calendarcontainer->ColumnDefinitions->Append(ref new Windows::UI::Xaml::Controls::ColumnDefinition());
    		calendarcontainer->ColumnDefinitions->Append(ref new Windows::UI::Xaml::Controls::ColumnDefinition());
    		calendarcontainer->ColumnDefinitions->Append(ref new Windows::UI::Xaml::Controls::ColumnDefinition());
    
    		calendarcontainer->RowDefinitions->Append(ref new Windows::UI::Xaml::Controls::RowDefinition());
    
    		calendarcontainer->Width = 1100;
    		calendarcontainer->Height = 700;
    		calendarcontainer->HorizontalAlignment = Windows::UI::Xaml::HorizontalAlignment::Center;
    		calendarcontainer->VerticalAlignment = Windows::UI::Xaml::VerticalAlignment::Center;
    
    		//calendarcontainer->RowDefinitions->Append(ref new Windows::UI::Xaml::Controls::RowDefinition());
    
    		dal =  ref new Calendar();
    		dal->Year = atoi((const char *)(wstring2string(rows.at(0)).c_str()));
    		dal->Month = 9;
    		dal->Day = dal->FirstDayInThisMonth;
    
    		daycounter = (int)dal->DayOfWeek;
    
    		for(day = 1; day <= dal->LastDayInThisMonth; day++)
    		{
    			rec = ref new Windows::UI::Xaml::Shapes::Rectangle();
    			rec->Style = safe_cast<Windows::UI::Xaml::Style ^>(Application::Current->Resources->Lookup("calendarStyle"));
    
    			forprintday = ref new TextBlock();
    			forprintday->Text = day.ToString();
    			forprintday->Style = safe_cast<Windows::UI::Xaml::Style ^>(Application::Current->Resources->Lookup("calendarDayText"));
    
    			calendarcontainer->Children->Append(rec);
    			calendarcontainer->Children->Append(forprintday);
    
    			calendarcontainer->SetColumn(forprintday, daycounter);
    			calendarcontainer->SetRow(forprintday, week);
    			calendarcontainer->SetColumn(rec, daycounter);
    			calendarcontainer->SetRow(rec, week);
    
    			daycounter++;
    			if(daycounter > 6)
    			{
    				calendarcontainer->RowDefinitions->Append(ref new Windows::UI::Xaml::Controls::RowDefinition());
    				week++;
    				daycounter = 0;
    			}
    		}
    		CalendarView->Items->Append(calendarcontainer);
    		CalendarView->UpdateLayout();
    		break;
    	}
    	create_task(create_async([this]{
    			makePages(2012, 9);
    	})).then([this]{
    		CalendarView->UpdateLayout();
    	});
    
    }
    
    void Dailibrary::DayViewPage::makePages(int year, int month)
    {
    	Canvas ^ basecanvas;
    	Grid ^ basegrid;
    	Windows::UI::Xaml::Shapes::Rectangle ^ snsIconBox;
    	Grid ^ innerGrid;
    	StackPanel ^ innerStack;
    	TextBlock ^ timeText;
    	TextBlock ^ contentsText;
    
    	Windows::UI::Xaml::Controls::ColumnDefinition ^ coldef;
    	Windows::UI::Xaml::Controls::RowDefinition ^ rowdef;
    
    	vector<vector<wstring>> result;
    	vector<wstring> rows;
    
    	int check [3][5] = {0};
    
    	int colcnt = 0;
    	int rowcnt = 0;
    
    	wstring querys = L"";
    	
    	querys += L"select uniqid, id, texts, contentspath, year, month, day, time from postsdata where year = ";
    	querys += year.ToString()->Data();
    	querys += L" and month = ";
    	querys += month.ToString()->Data();
    	querys += L" order by day asc;";
    	
    	result = db->query((wchar_t*)querys.c_str());
    
    	basecanvas = ref new Windows::UI::Xaml::Controls::Canvas();
    	basecanvas->Width = 1200;
    	basecanvas->Height = 750;
    
    	basegrid = ref new Grid();
    	basegrid->Width = 1200;
    	basegrid->Height = 750;
    
    	basegrid->ColumnDefinitions->Append(ref new Windows::UI::Xaml::Controls::ColumnDefinition());
    	basegrid->ColumnDefinitions->Append(ref new Windows::UI::Xaml::Controls::ColumnDefinition());
    	basegrid->ColumnDefinitions->Append(ref new Windows::UI::Xaml::Controls::ColumnDefinition());
    
    	basegrid->RowDefinitions->Append(ref new Windows::UI::Xaml::Controls::RowDefinition());
    	basegrid->RowDefinitions->Append(ref new Windows::UI::Xaml::Controls::RowDefinition());
    	basegrid->RowDefinitions->Append(ref new Windows::UI::Xaml::Controls::RowDefinition());
    	basegrid->RowDefinitions->Append(ref new Windows::UI::Xaml::Controls::RowDefinition());
    	basegrid->RowDefinitions->Append(ref new Windows::UI::Xaml::Controls::RowDefinition());
    
    	for(vector<vector<wstring>>::iterator it = result.begin(); it < result.end(); it++)
    	{
    		rows = *it;
    
    		innerGrid = ref new Grid();
    		coldef = ref new Windows::UI::Xaml::Controls::ColumnDefinition();
    		coldef->Width = Windows::UI::Xaml::GridLength::Auto;
    		innerGrid->ColumnDefinitions->Append(coldef);
    		innerGrid->ColumnDefinitions->Append(ref new Windows::UI::Xaml::Controls::ColumnDefinition);
    
    		innerStack = ref new StackPanel();
    
    		snsIconBox = ref new Windows::UI::Xaml::Shapes::Rectangle();
    		snsIconBox->Style = safe_cast<Windows::UI::Xaml::Style ^>(Application::Current->Resources->Lookup("IconBrushFacebook"));
    
    		timeText = ref new TextBlock();
    		timeText->Style = safe_cast<Windows::UI::Xaml::Style ^>(Application::Current->Resources->Lookup("TimeText"));;
    		timeText->Text = ref new String(rows.at(7).c_str());
    
    		contentsText = ref new TextBlock();
    		contentsText->Style = safe_cast<Windows::UI::Xaml::Style ^>(Application::Current->Resources->Lookup("ContentsText"));;
    		contentsText->Text = ref new String(rows.at(2).c_str());
    
    		innerStack->Children->Append(snsIconBox);
    		innerStack->Children->Append(timeText);
    
    		innerGrid->Children->Append(innerStack);
    		innerGrid->SetColumn(innerStack, 0);
    		innerGrid->Children->Append(contentsText);
    		innerGrid->SetColumn(contentsText, 1);
    		
    		basegrid->Children->Append(innerGrid);
    		basegrid->SetColumn(innerGrid, colcnt);
    		basegrid->SetRow(innerGrid, rowcnt);
    
    		rowcnt++;
    		if(rowcnt > 4)
    		{
    			rowcnt = 0;
    			colcnt++;
    		}
    		if(colcnt > 2)
    		{
    			colcnt = 0;
    			rowcnt = 0;
    
    			basecanvas->Children->Append(basegrid);
    			basecanvas->SetTop(basegrid, 0);
    			basecanvas->SetLeft(basegrid, 0);
    
    			CalendarView->Items->Append(basecanvas);
    
    			basecanvas = ref new Canvas();
    
    			basecanvas->Width = 1200;
    			basecanvas->Height = 750;
    
    			basegrid = ref new Grid();
    			basegrid->Width = 1200;
    			basegrid->Height = 750;
    
    			basegrid->ColumnDefinitions->Append(ref new Windows::UI::Xaml::Controls::ColumnDefinition());
    			basegrid->ColumnDefinitions->Append(ref new Windows::UI::Xaml::Controls::ColumnDefinition());
    			basegrid->ColumnDefinitions->Append(ref new Windows::UI::Xaml::Controls::ColumnDefinition());
    
    			basegrid->RowDefinitions->Append(ref new Windows::UI::Xaml::Controls::RowDefinition());
    			basegrid->RowDefinitions->Append(ref new Windows::UI::Xaml::Controls::RowDefinition());
    			basegrid->RowDefinitions->Append(ref new Windows::UI::Xaml::Controls::RowDefinition());
    			basegrid->RowDefinitions->Append(ref new Windows::UI::Xaml::Controls::RowDefinition());
    			basegrid->RowDefinitions->Append(ref new Windows::UI::Xaml::Controls::RowDefinition());
    		}
    	}
    }

    여기에서 비동기로 함수호출이 됩니다.

    추적을 해보니, Xaml을 코드로 생성하는 부분에서 예외가 발생하는데...

    원인을 모르겠습니다.ㅜㅜ 도와주세요.....


    Dr.Luis

    • 이동됨 Jina Lee 2012년 10월 23일 화요일 오전 7:44 (이전 위치:Windows 스토어 앱)
    2012년 9월 25일 화요일 오전 11:25

답변

  • create_async 메서드로 전달된 함수는 별도의 쓰레드에서 실행됩니다. 따라서, 그 함수내에서 UI를 건드려서는 안됩니다.

    비동기 함수에서는 가능한 한 데이터만을 가져오고, 그 이후에 그 데이터를 바탕으로 UI를 생성하는 식으로 바꿔야 합니다. 가령 위와 같은 경우에는 db->query 만 create_async에서 처리하고, 이후의 result 쿼리 결과를 바탕으로 한 UI 생성 코드는 .then 으로 시작하는 continuation 절에서 처리를 해주는 식으로 바꿔야 합니다.

    • 답변으로 표시됨 DrLuis 2012년 9월 26일 수요일 오전 5:13
    2012년 9월 25일 화요일 오후 3:44
  • 응답이 없는 것이 맞습니다. 어쩔 수 없습니다.

    가능한 그런 경우를 위해서 UI 항목들을 가상화하는 기술이 그래서 제공되는 것입니다.

    VirtualizingStackPanel class
    ; http://msdn.microsoft.com/en-us/library/windows/apps/xaml/windows.ui.xaml.controls.virtualizingstackpanel.aspx

    • 답변으로 표시됨 Jina Lee 2012년 10월 2일 화요일 오전 8:12
    2012년 9월 26일 수요일 오전 7:01

모든 응답

  • create_async 메서드로 전달된 함수는 별도의 쓰레드에서 실행됩니다. 따라서, 그 함수내에서 UI를 건드려서는 안됩니다.

    비동기 함수에서는 가능한 한 데이터만을 가져오고, 그 이후에 그 데이터를 바탕으로 UI를 생성하는 식으로 바꿔야 합니다. 가령 위와 같은 경우에는 db->query 만 create_async에서 처리하고, 이후의 result 쿼리 결과를 바탕으로 한 UI 생성 코드는 .then 으로 시작하는 continuation 절에서 처리를 해주는 식으로 바꿔야 합니다.

    • 답변으로 표시됨 DrLuis 2012년 9월 26일 수요일 오전 5:13
    2012년 9월 25일 화요일 오후 3:44
  • 아! 그렇군요! 감사합니다.!

    그럼 혹시 비동기로 UI를 컨트롤할수있는 방법도 있나요.?


    Dr.Luis

    2012년 9월 26일 수요일 오전 5:18
  • UI는 비동기로 하시면 안됩니다. 좀더 원칙적으로 말씀드려보면, 해당 UI 를 생성한 쓰레드만이 그 UI를 접근해야 합니다. 이 점은 과거 Win32 시절부터 있던 문제인데요. 그 당시에는 '예외'까지는 아니고 신입 개발자 입장에서는 알 수 없는 '데이터 누락'현상 등으로 나타났었습니다. 그런 것이, .NET 에 와서는 아예 강제 사항으로 바뀌었고요. WinRT 프로그램도 그것을 따라 UI 요소를 생성한 쓰레드가 아닌 다른 쓰레드에서는 UI 요소를 건드릴 수 없도록 강제사항이 적용되고 있는 것입니다.
    2012년 9월 26일 수요일 오전 5:47
  • 그렇다면 저 코드처럼 for문돌면서 하나씩추가하는 경우에는 그냥 돌려야 하는건가요?

    만약 데이터가 많을경우 앱이 응답을 기다리면서 가만히 있거나 하진 않을까요?


    Dr.Luis

    2012년 9월 26일 수요일 오전 6:41
  • 응답이 없는 것이 맞습니다. 어쩔 수 없습니다.

    가능한 그런 경우를 위해서 UI 항목들을 가상화하는 기술이 그래서 제공되는 것입니다.

    VirtualizingStackPanel class
    ; http://msdn.microsoft.com/en-us/library/windows/apps/xaml/windows.ui.xaml.controls.virtualizingstackpanel.aspx

    • 답변으로 표시됨 Jina Lee 2012년 10월 2일 화요일 오전 8:12
    2012년 9월 26일 수요일 오전 7:01